Git:如何获取所有更改的文件以及文件夹或zip中的新文件?


72

正如我的问题所述,在更改文件并在存储库中添加新文件后,我通常使用git提交文件,但有时出于组织原因,我需要将所有已修改/更改的文件复制到文件夹中。

有什么选择吗?


如果您告诉我们您实际要完成的工作,那么我们的答案可能会更有帮助。
卡斯卡贝尔

这取决于,有时仅是通过ftp传输
先生问题,2010年

但是“ ftp他们”本身并不是一个目标。这样做的理由是什么?我从来不想只为更改过的文件创建一个zip,所以我想知道用例。
斯文·马纳赫

在这种情况下,它更多的是将它们复制到文件夹,而不是拉拉链
问先生

Answers:


109

假设您尚未提交,并且想打包当前已进行本地修改的所有文件,则可以使用来获取已修改文件的列表git ls-files --modified。如果要使用上次提交更改的文件,可以使用git diff --name-only HEAD^。从那里到哪里,取决于您。例子:

zip modified-files.zip $(git ls-files --modified)
cp $(git ls-files --modified) ../modified-files

请注意,这当前正在使用工作树中的文件版本。

如果文件名中有空格,则将不得不麻烦一点。

(当然,根据您的实际意图,您可能正在寻找 git stash,它将藏匿所有已修改的文件并留下干净的工作树,或者您可能只是想制作一个临时分支来提交。 )


1
这是无需提交的,我也该如何获取新文件。
问题先生,2010年

当我说新文件时,这意味着将它们添加到资源库之前
先生问题,2010年

2
我想我找到了我想要的东西:cp $(git ls-files --modified --others)修改过的文件。多谢。
先生的问题

无论如何,是否要排除某些扩展名或文件名甚至子文件夹?
问题先生,2010年

11
使用--parents复制和创建文件夹:cp --parents $(git ls-files --modified)../copyfolder/
Russell England

68

要完全按照您的要求进行操作(假设您已经提交并想要创建上次提交更改的文件的存档),可以执行以下操作:

git archive --format=zip HEAD `git diff HEAD^ HEAD --name-only` > a.zip

如果您已删除提交中的文件,为防止出现pathspec错误,请使用--diff-filter=d

git archive --format=zip HEAD `git diff --diff-filter=d HEAD^ HEAD --name-only` > a.zip

但是也许您实际上想使用以下方法创建补丁:

git diff HEAD^ HEAD > a.patch

并使用以下命令在需要的地方应用此补丁:

patch -p1 < a.patch

当然,仅当目标目录已包含存储库的旧版本时,才应用补丁。


1
我建议使用git format-patch而不是管道git diff传输文件
knittl

1
这是在提交后,如何也可以获取新文件。
“问题先生”,2010年

2
一个问题是,当您删除某些内容时,会出现错误:“致命:找不到路径:XYZ”
Krzysztof Romanowski

1
git archive非常适合我。我必须获得最后2次提交,所以我做了其中之一:git archive --format=zip HEAD `git diff HEAD~2 HEAD --name-only` > a.zip
j.snyder 2013年

1
在Windows(7)上,此答案中的第一个命令对我不起作用。由于某种原因,它抱怨--name-only选项未知。我认为这可能只是一个逃避的问题?因此,我很懒惰,安装了Cygwin并能够从Cygwin提示符下正确运行它。
约翰·布布里斯基

16

如果您使用TortoiseGIt,它也提供此功能。
在资源管理器中选择文件夹,
右键单击,选择菜单,TortoiseGit->显示日志。

选择工作目录和最后提交的版本。
右键点击。比较修订。选择要保存/导出的文件。
右键点击。导出到文件夹。做完了


我希望TortoiseGit导出工具允许您选择多个提交。
Corgalore

7

在git仓库中压缩修改过的和新创建的文件

zip mychanges.zip $({ (git ls-files --others --exclude-standard) ; (git ls-files --modified)})

3

假设您没有删除或重命名文件,这应该可以解决问题

复制:

cp --parents $(git status -s | egrep "M|A|AM" | rev | cut -d" " -f1 | rev) destination_folder

压缩:

zip modified.zip $(git status -s | egrep "M|A|AM" | rev | cut -d" " -f1 | rev)

cp --parents似乎与文件一起复制/创建目录,有没有办法在文件上复制而不创建目录。我猜想删除--parents参数就可以了:)。
Rainu

--parents使用DIRECTORY下的完整源文件名。--parents参数将文件放置在与原始文件相同的目标文件夹结构中。例如,如果您在include和source文件夹上修改了文件,则--parents参数将它们放在目标的include和source中。[orig / folder_a / file_1,orig / folder_b / file_2]-> [dest / folder_a / file_1,dest / folder_b / file_2]如果在同一项目的不同文件夹中修改了文件(例如include和source),这将非常有用文件夹)
BRT

如果添加“ ??” 到egrep“ M | A | AM | ??”到egrep“ M | A | AM”,您还将复制不受版本控制的文件。这对于尚未添加或提交的新文件很有用
BRT

当我添加“ M | A | AM | ??”时 我得到:egrep: repetition-operator operand invalid。😞–
Chance Smith

我正在使用GNU grep 3.3(2018-05-11)
BRT

1
mkdir -p /c/temp/blah && cp $(git diff <your commit hash> --name-only) /c/temp/blah

我在Windows上使用Git Bash。


0

这是一个脚本,它可以使此过程更加轻松,它将所有更改的文件复制到使用的已定义目录中,并维护代码库的目录结构。

运行:sh scr.sh

================================================

#!/bin/sh
FILES=`git ls-files --modified`
for x in $FILES
do
        prev_dir=$PWD
        echo "MY Dir = $prev_dir"
        mkdir -p $1/$x
        cd $1/$x
        cd ../
        rm -r *
        cp $prev_dir/$x ./.
        cd $prev_dir
done

================================================


如何检查FILES为空,并在终端屏幕上显示消息并设置目标文件夹?
May'Habit

我更改根文件夹中的文件并运行您的命令,它将创建一个具有相同名称的文件夹。为什么不将文件复制到另一个文件夹而是创建文件夹?
May'Habit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.