【问题标题】:git cherry-pick does not just pick the diff of the commitgit cherry-pick 不只是选择提交的差异
【发布时间】:2017-07-23 03:17:23
【问题描述】:

我有两个分支:AB

  • A 的提交历史:a <- b <- c;
  • B 的提交历史:a <- h <- i;

假设这里只有一个文件。

  1. 在提交 b 中,我添加了一些文本,例如“foo”。
  2. 在提交c 中,我添加了一些文本,例如“bar”。
  3. 然后我在 B 分支上 git cherry-pick c。我以为cherry-pick 只会选择c 中的更改到分支B。但是,它会将foobar 添加到分支B。这显然不是我想要的。

因此,cherry-pick 将选择自祖先提交a 以来提交c 中涉及的那些文件的所有更改。那正确吗?如果我只想选择从bc 的差异并将其应用于i,该怎么办?

更新具体步骤

  1. 初始化一个 git repo;
  2. 添加文件test.txt 并发出第一个提交init committest.txt 现在是:

    first line  
    second line
    
  3. 创建一个新分支dev,但留在分支master

  4. added in commit b 添加到文件并发出提交btest.txt 现在是:

    first line
    added in commit b
    second line
    
  5. added in commit c 添加到文件并发出提交ctest.txt 现在是:

    first line
    added in commit b
    added in commit c
    second line
    
  6. 签出dev 分支并提交htest.txt 现在是:

    first line
    second line
    
    adding by commit h
    
  7. git cherry-pick <commit c SHA1 ID> 到cherry-pick 提交c 到提交h

  8. 冲突信息:

    index 6a8dc57,594c6ec..0000000
    @@@ -1,4 -1,4 +1,9 @@@
      first line
    ++<<<<<<< HEAD
    ++=======
    + added in commit b
    + added in commit c
    ++>>>>>>> 06ce9b1... commit c adding another line
      second line
     +
     +adding by commit h
    
  9. 看到了吗? cherry-pick 还带来了提交中的更改 b

谢谢!

【问题讨论】:

  • 这可能对你有帮助stackoverflow.com/questions/9339429/…
  • @ArunG 谢谢!我知道cherry-pick 是什么意思。但我只是感到困惑,它不等于获取该提交的差异并将差异应用于目标分支。它还包含该提交中的 NOT 内容。
  • @tamlok,运行 git show a(显然用相关的提交 SHA 替换 a)来检查提交实际上会引入的更改,以了解为什么您可能会从提交 b 获得增量。您始终可以使用 -n 标志运行 cherry-pick 来停止并手动删除不需要的更改。
  • 请显示命令的确切顺序(包括您用于显示精选提交的内容)。我认为你误解了你所看到的。
  • @MikeMB 请查看更新。谢谢!

标签: git cherry-pick


【解决方案1】:

git cherry-pick 尝试只带来一个提交。但它通过应用需要一些上下文的补丁来做到这一点。提交 C 中所做的更改与提交 b 所做的更改非常接近,因此您会遇到冲突 - 它不能只是找到必须应用更改的正确位置。当你有冲突时,你也会得到一些冲突的上下文,这至少是你的提交 B 的一部分。

在没有冲突的情况下它是如何工作的:

$ git init
$ cat > f
line1
line2
line3
$ git add f
$ git commit -a -m "initial"
# Edited to add a line in the beginning of f
$ cat f
Commit b
line1
line2
line3
$ git commit f -m "B"
# Edited to add a line in the end of f
$ cat f
Commit b
line1
line2
line3
Commit c
$ git commit f -m "C"
$ git checkout HEAD^^
$ git cherry-pick master
$ cat f
line1
line2
line3
Commit c

【讨论】:

  • 所以git cherry-pick master 只会选择提交c 而不是bc?那就是当使用带有git cherry-pick 的分支名称时,它只会选择最后一次提交?谢谢!
  • 我刚试过git cherry-pick master。结果是一样的,冲突内容还是包含了commitb的改动。 :(
  • 知道了!谢谢!
【解决方案2】:

如果我只想选择从 b 到 c 的差异并将其应用到 i 上呢?

您可以在两次提交之间找到/写入文件的diff (c..d)。然后将其应用到您当前的分支中。

$ git checkout <B-branch>

# write the diff in a file named 'change.patch' (root directory) 
$ git diff <b-commit> <c-commit> <file-name> >> ~/changes.patch

$ git apply ~/changes.patch       # apply the changes
$ git add .

# merge the changes to i (previous commit)
$ git commit --amend -m 'Apply the diff of b and c'

$ git push -f origin HEAD      # force(-f) push since history is changed

【讨论】:

  • 我知道这种“原始”方式。但是根据git cherry-pick 的描述,为什么它还会从其他未指定的提交中选择额外的更改?谢谢!
  • 在我的例子中,补丁没有完全应用,所以我必须使用--3way 选项进行三向合并。然后我得到与使用git cherry-pick 完全相同的结果,除了错误被静音并且它似乎回落到没有抬头的三向。我仍然不明白为什么三路合并最终会得到这个结果,但是我的两个分支已经分歧了很多,所以这可能是相关的。
猜你喜欢
  • 2021-01-18
  • 1970-01-01
  • 2012-11-05
  • 2018-04-17
  • 2012-05-21
  • 2016-10-24
  • 2017-05-31
  • 2016-04-11
  • 2018-04-16
相关资源
最近更新 更多