在Git中只导出修改和添加文件夹结构的文件

我想在特定的提交中获取已修改和添加的文件的列表,以便我可以导出它们并生成具有文件结构的包。

这个想法是获取包并将其提取到服务器上。 由于许多原因,我不能创build一个钩子来自动拉回购,我必须保持服务器更新的最简单的方法是生成这个包。

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id 
  1. git diff-tree -r $commit_id

    将给定提交的差异传递给其父(包括所有子目录,而不仅仅是顶级目录)。

  2. --no-commit-id --name-only

    不要输出提交SHA1。 只输出受影响的文件的名称而不是完整的差异。

  3. --diff-filter=ACMRT

    只显示在此提交中添加,复制,修改,重命名或其types已更改的文件(例如文件→符号链接)。 这留下了删除的文件。

 git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | xargs tar -rf mytarfile.tar 

只是为了完成这个,这里是用tar命令。 这将文件导出到一个tar档案。

这是一个可以在Windows 7上运行的单行命令。从存储库的顶级文件夹运行它。

(`git diff-tree -r –no-commit-id –name-only –diff-filter = ACMRT HEAD〜1 HEAD`)/ f“usebackq tokens = *”%A in echo FA | xcopy “%〜fA”“C:\ git_changed_files \%A”

  • 回声FA回答关于是否复制文件或目录(文件)不可避免的xcopy问题,以及覆盖文件(覆盖全部)的可能问题
  • usebackq允许我们使用git命令的输出作为do子句的input
  • HEAD〜1 HEAD获取前一个提交和当前HEAD之间的所有差异
  • %〜fA将git输出转换为完全限定的path(需要将正斜杠更改为反斜杠)
  • C:\ git_changed_files \是您可以find所有不同的文件的地方

如果你的提交散列是例如a9359f9,这个命令:

git archive -o patch.zip a9359f9 $(git diff --name-only a9359f9^..a9359f9)

将提取提交中修改的文件,并将其放在patch.zip中,同时保持项目目录结构不变。

有点冗长,提交散列提到三次,但它似乎为我工作。

得到它在这里: http : //tosbourn.com/2011/05/git/using-git-to-create-an-archive-of-changed-files/

我需要更新我的testing服务器并添加从版本2.1以来更改的文件。
对于我来说,James Ehly发布了类似的解决scheme,但在我的情况下,我希望导出到两个较旧的标记(tag_ver_2.1和tag_ver_2.2不是唯一的一个提交)之间的区别。

例如:

tag_ver_2.1 = 1f72b38ad
tag_ver_2.2 = c1a546782

这里是修改的例子:

 git diff-tree -r --no-commit-id --name-only c1a546782 1f72b38ad | xargs tar -rf test.tar 

您可以使用Tortoise Git将差异导出到MS Windows:

我右键单击并selectTortoiseGit > 显示日志日志消息将被打开。

select两个修订版本并进行比较。 之间的区别将被打开。

select文件和导出select…到一个文件夹!

在这里输入图像描述

我已经做了一个PHP脚本导出在Windows上更改的文件。 如果你有一个PHP设置的本地开发服务器,那么你可以很容易地运行它。 它会记住你的上一个版本库并且总是导出到同一个文件夹。 导出文件夹在导出之前总是被清空。 您还将看到红色的已删除文件,以便您知道要在服务器上删除的内容。

这些只是两个文件,所以我会在这里发表。 假设您的存储库位于c:/ www下的自己的文件夹中,并且http:// localhost也指向c:/ www并启用了php。 让我们把这两个文件放在c:/ www / git-export –

index.php:

 <?php /* create directory if doesn't exist */ function createDir($dirName, $perm = 0777) { $dirs = explode('/', $dirName); $dir=''; foreach ($dirs as $part) { $dir.=$part.'/'; if (!is_dir($dir) && strlen($dir)>0) { mkdir($dir, $perm); } } } /* deletes dir recursevely, be careful! */ function deleteDirRecursive($f) { if (strpos($f, "c:/www/export" . "/") !== 0) { exit("deleteDirRecursive() protection disabled deleting of tree: $f - please edit the path check in source php file!"); } if (is_dir($f)) { foreach(scandir($f) as $item) { if ($item == '.' || $item == '..') { continue; } deleteDirRecursive($f . "/" . $item); } rmdir($f); } elseif (is_file($f)) { unlink($f); } } $lastRepoDirFile = "last_repo_dir.txt"; $repo = isset($_POST['repo']) ? $_POST['repo'] : null; if (!$repo && is_file($lastRepoDirFile)) { $repo = file_get_contents($lastRepoDirFile); } $range = isset($_POST['range']) ? $_POST['range'] : "HEAD~1 HEAD"; $ini = parse_ini_file("git-export.ini"); $exportDir = $ini['export_dir']; ?> <html> <head> <title>Git export changed files</title> </head> <body> <form action="." method="post"> repository: <?=$ini['base_repo_dir'] ?>/<input type="text" name="repo" value="<?=htmlspecialchars($repo) ?>" size="25"><br/><br/> range: <input type="text" name="range" value="<?=htmlspecialchars($range) ?>" size="100"><br/><br/> target: <strong><?=$exportDir ?></strong><br/><br/> <input type="submit" value="EXPORT!"> </form> <br/> <?php if (!empty($_POST)) { /* ************************************************************** */ file_put_contents($lastRepoDirFile, $repo); $repoDir = $ini['base_repo_dir'] ."/$repo"; $repoDir = rtrim($repoDir, '/\\'); echo "<hr/>source repository: <strong>$repoDir</strong><br/>"; echo "exporting to: <strong>$exportDir</strong><br/><br/>\n"; createDir($exportDir); // empty export dir foreach (scandir($exportDir) as $file) { if ($file != '..' && $file != '.') { deleteDirRecursive("$exportDir/$file"); } } // execute git diff $cmd = "git --git-dir=$repoDir/.git diff $range --name-only"; exec("$cmd 2>&1", $output, $err); if ($err) { echo "Command error: <br/>"; echo implode("<br/>", array_map('htmlspecialchars', $output)); exit; } // $output contains a list of filenames with paths of changed files foreach ($output as $file) { $source = "$repoDir/$file"; if (is_file($source)) { if (strpos($file, '/')) { createDir("$exportDir/" .dirname($file)); } copy($source, "$exportDir/$file"); echo "$file<br/>\n"; } else { // deleted file echo "<span style='color: red'>$file</span><br/>\n"; } } } ?> </body> </html> 

git-export.ini:

 ; path to all your git repositories for convenience - less typing base_repo_dir = c:/www ; if you change it you have to also change it in the php script ; in deleteDirRecursive() function - this is for security export_dir = c:/www/export 

现在在浏览器中加载localhost / git-export /。 该脚本设置为始终导出到c:/ www / export – 更改所有path以适合您的环境,或修改脚本以满足您的需求。

这将工作,如果你有Git安装,使git命令在你的path – 这可以configuration当你运行的Windows Git安装程序。

从date开始导出修改的文件:

  diff --stat @{2016-11-01} --diff-filter=ACRMRT --name-only | xargs tar -cf 11.tar 

快捷方式(使用别名)

  git exportmdf 2016-11-01 11.tar 

.gitconfig中的别名

  [alias] exportmdf = "!f() { \ git diff --stat @{$1} --diff-filter=ACRMRT --name-only | xargs tar -cf $2; \ }; f"