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

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


当前回答

我找到了另一种方法来防止樱桃采摘上的任何冲突合并,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

其他回答

Cherry pick是从特定的“提交”中选择更改。最简单的解决方案是选择某些文件的所有更改

 git checkout source_branch <paths>...

例如:

$ git branch
* master
  twitter_integration
$ git checkout twitter_integration app/models/avatar.rb db/migrate/20090223104419_create_avatars.rb test/unit/models/avatar_test.rb test/functional/models/avatar_test.rb
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   app/models/avatar.rb
#   new file:   db/migrate/20090223104419_create_avatars.rb
#   new file:   test/functional/models/avatar_test.rb
#   new file:   test/unit/models/avatar_test.rb
#
$ git commit -m "'Merge' avatar code from 'twitter_integration' branch"
[master]: created 4d3e37b: "'Merge' avatar code from 'twitter_integration' branch"
4 files changed, 72 insertions(+), 0 deletions(-)
create mode 100644 app/models/avatar.rb
create mode 100644 db/migrate/20090223104419_create_avatars.rb
create mode 100644 test/functional/models/avatar_test.rb
create mode 100644 test/unit/models/avatar_test.rb

来源和完整解释http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/

更新:

使用此方法,git不会合并文件,它只会覆盖在目标分支上所做的任何其他更改。您需要手动合并更改:

$git diff HEAD文件名

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

git reset --soft HEAD^

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

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

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

自动化程度更高:

#!/usr/bin/env bash

filter_commit_to_files() {
    FILES="$1"
    SHA="$2"
    git show "$SHA" -- $FILES | git apply --index -
    git commit -c "$SHA"
}

示例用法:

filter_commit_to_files "file1.txt file2.txt" 07271c5e

我通过复制并粘贴到外壳中来定义它。您不需要here文档。

我通常将-p标志与来自其他分支的git签出一起使用,我发现这比我遇到的大多数其他方法更容易和更精细。

原则上:

git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p

例子:

git checkout mybranch config/important.yml app/models/important.rb -p

然后,您会看到一个对话框,询问您希望在“blobs”中进行哪些更改,这基本上适用于连续代码更改的每个块,然后您可以为每个代码块发出y(是)n(否)等信号。

-p或patch选项适用于git中的各种命令,包括git stash save-p,它允许您从当前工作中选择要隐藏的内容

当我做了很多工作,并希望将其分离出来,使用gitadd-p提交更多基于主题的提交,并选择每次提交所需的内容时,我有时会使用此技术:)