如何仅选择一个文件而不是整个提交的变更


Answers:


137

根据要实现的目标,您有不同的选择:

如果希望文件的内容与目标分支上的相同,则可以使用git checkout <branch> -- <filename>。但是,这不会“挑剔”一次提交中发生的更改,而只是获取所述文件的结果状态。因此,如果您在提交中添加了一行,但是以前的提交进行了更多更改,而您只想添加该行而不进行其他更改,那么结帐就不是您想要的。

否则,如果您要将提交中引入的补丁仅应用于单个文件,则可以有多个选项。您可以运行git cherry-pick -n,即不提交就编辑提交(例如使用重置所有文件,git reset -- .而仅使用实际添加要更改的文件git add <filename>)。或者,您可以为文件创建差异,然后应用差异:

git diff <branch>^..<branch> -- <filename> | git apply

22

创建一个patch file并应用它。

git diff branchname -- filename > patchfile
git apply patchfile

编辑:

由于您需要从提交中进行更改,因此请创建补丁,如下所示:

git show sha1 -- filename > patchfile

1
git diff sha1(或者git diff branch-如果分支指向相同的散列,则是相同的)将仅产生与该散列相关的当前工作目录的差异,而不会产生自己更改引入的更改。

正确。编辑答案。谢谢。
Sailesh

1
git checkout带有文件名的-1 是此钉子的正确锤子。这两个选项都不必要地复杂。
Rein Henrichs

7
对于这种特殊情况,是的。但是总的来说,如果您想从对特定文件的提交中选择更改,checkout则将不起作用,因为它可能涉及其他先前不需要的更改,并且可能不包含在当前分支中所做的更改。
Sailesh

11

另一个方便的事情是在本地获取补丁,然后使用:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

不过那不是挑剔的。


2
警告:正如@poke在他的回答中所说,这不会复制更改;它复制文件的整个状态。因此,如果您要将提交的更改添加到文件中,则通过像这样签出,最终会覆盖不好的任何新更改。
亚历山大·伯德

7

Git已经准备就绪:)

只需使用 git checkout <sha> <path-to-file>


4
这不是挑剔的选择,而是将文件全部签出。目标是对提交进行特定更改。通常这些都是同一回事,但有时却不是。
AndrewF

6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

如果您希望将另一个分支中的单个文件复制到当前工作分支中,则此方法有效


1
请注意,文件中所做的,与其他分支版本不同的更改将丢失。
PatrickSchlüter'17

同意这一点。如果您只需要文件的副本,并且想要在当前分支上更改它,这将很有用
Ismail Iqbal'May

1
一个人可以使用glob(path / *)并指定多个路径/文件
Todd


1

我倾向于做的是使用 git ls-tree

做就是了:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

这将打印与您的grep匹配的所有文件名,并在提交中提供文件的SHA1密钥。

Git show也可以在分支机构之外的文件上使用。使用>您的shell将输出通过管道传输到文件中,可以为您提供所需的结果。


0

您可以尝试这样做:

git show COMMIT_ID -- path/to/specific-file | git apply

例如:

git show 3feaf20 -- app/views/home/index.html | git apply

-9
git reset HEAD~1

将文件移到预提交阶段

git stash

从内存中删除

现在,您的分支非常干净(还原为先前的提交)

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.