如果我想合并到Git分支中,而只对某些提交中的某些文件所做的更改(包括对多个文件的更改)进行更改,那么如何实现呢?

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


#1楼

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文件名


#2楼

我只是挑选所有内容,然后执行以下操作:

git reset --soft HEAD^

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


#3楼

其他方法对我不起作用,因为提交有很多更改,并且与许多其他文件存在冲突。 我想出的只是

git show SHA -- file1.txt file2.txt | git apply -

它实际上不会add文件或为您执行提交,因此您可能需要跟进

git add file1.txt file2.txt
git commit -c SHA

或者,如果要跳过添加,则可以使用--cached参数进行git apply

git show SHA -- file1.txt file2.txt | git apply --cached -

您还可以对整个目录执行相同的操作

git show SHA -- dir1 dir2 | git apply -

#4楼

我通常将-p标志与其他分支的git checkout一起使用,与我遇到的大多数其他方法相比,我发现它更容易且更精细。

原则上:

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

然后,您会看到一个对话框,询问您要在“ blob”中进行哪些更改,这几乎可以解决连续代码更改的每个块,然后您可以为每个代码块发出y (是) n (否)等信号。

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

当我做了很多工作时,有时我会使用这种技术,想将其分离出来,并使用git add -p提交更多基于主题的提交,并为每次提交选择想要的内容:)


#5楼

我发现了另一种方法,可以防止在进行樱桃选择时发生任何冲突合并,而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

现在您可以删除temp分支:

$ git branch -d temp -f

#6楼

使用git merge --squash branch_name可以从另一个分支获取所有更改,并为您准备提交。 现在,删除所有不需要的更改,然后保留所需的更改。 git不会知道有合并。


#7楼

将一个分支合并到一个新的(南瓜)中,并删除不需要的文件:

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

#8楼

情况:

您在您的分支上,比方说master ,您在其他任何分支上都有提交。 您只需要从该特定提交中选择一个文件。

该方法:

步骤1:在所需分支上签出。

git checkout master

步骤2:确保已复制所需的提交哈希。

git checkout commit_hash path\to\file

步骤3:现在,您可以在所需分支上更改所需文件。 您只需要添加并提交它们。

git add path\to\file
git commit -m "Your commit message"

#9楼

也许这种方法优于Jefromi的答案的优点是您不必记住git reset的哪种行为才是正确的:)

 # Create a branch to throw away, on which we'll do the cherry-pick:
 git checkout -b to-discard

 # Do the cherry-pick:
 git cherry-pick stuff

 # Switch back to the branch you were previously on:
 git checkout -

 # Update the working tree and the index with the versions of A and B
 # from the to-discard branch:
 git checkout to-discard -- A B

 # Commit those changes:
 git commit -m "Cherry-picked changes to A and B from [stuff]"

 # Delete the temporary branch:
 git branch -D to-discard

#10楼

我会用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 .

#11楼

您可以使用:

git diff <commit>^ <commit> -- <path> | git apply

符号<commit>^指定的(第一)父<commit> 。 因此,此diff命令在commit <commit>选择对<path>所做的更改。

注意,这还不会提交任何东西(就像git cherry-pick一样)。 因此,如果您需要这样做,则必须执行以下操作:

git add <path>
git commit

#12楼

为了完善起见,最适合我的是:

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

git status

它正是OP想要的。 在需要时,它会解决冲突,类似地,如何merge 。 它确实add但不commit新更改。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐