如果我想将仅对特定提交中更改的部分文件(包括对多个文件的更改)进行的更改合并到Git分支中,如何实现这一点?

假设名为stuff的Git提交对文件A、B、C和D进行了更改,但我只想将stuff的更改合并到文件A和B。这听起来像Git cherry-pick的工作,但cherry pick只知道如何合并整个提交,而不是文件的子集。


当前回答

为了完整,最适合我的是:

git show YOURHASH --no-color -- file1.txt file2.txt dir3 dir4 | git apply -3 --index -

这正是OP想要的。它在需要时进行冲突解决,类似于合并的方式。它会添加但不会提交新的更改,请参阅状态。

其他回答

我会选择一切,然后这样做:

git reset --soft HEAD^

然后我会还原我不想要的更改,然后进行新的提交。

我会使用cherry-pick-n(--no-commit)来完成,它允许您在提交之前检查(和修改)结果:

git cherry-pick -n <commit>

# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>

# commit; the message will have been stored for you by cherry-pick
git commit

如果绝大多数修改都是您不想要的,那么您可以重新设置所有内容,然后添加您想要的内容,而不是检查各个路径(中间步骤):

# unstage everything
git reset HEAD

# stage the modifications you do want
git add <path>

# make the work tree match the index
# (do this from the top level of the repo)
git checkout .

有时,使用签出从提交中获取特定文件可能更容易。在我看来,它给了你更多的控制权,而且在樱桃采摘后不必检查和拆封。

我会这样做:

git checkout <branch|hash> -- path/to/file1 path/to/filen

然后,在提交之前,取消编写必要的更改以适应代码并对其进行测试。如果一切按预期进行,那么提交。

我找到了另一种方法来防止樱桃采摘上的任何冲突合并,IMO很容易记住和理解。因为您实际上不是在挑选提交,而是其中的一部分,所以您需要先拆分它,然后创建一个符合您需要的提交,然后再挑选它。

首先从要拆分并签出的提交创建分支:

$ git checkout COMMIT-TO-SPLIT-SHA -b temp

然后恢复上一次提交:

$ git reset HEAD~1

然后添加您要选择的文件/更改:

$ git add FILE

并提交:

$ git commit -m "pick me"

请注意提交散列,让我们将其称为PICK-SHA,然后返回主分支,例如master强制结账:

$ git checkout -f master

和樱桃选择承诺:

$ git cherry-pick PICK-SHA

现在可以删除临时分支:

$ git branch -d temp -f

将分支合并为新分支(挤压)并删除不需要的文件:

git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit