git - 如果它们不同,为什么 gitcherry-pick 不覆盖当前分支中的修改?

标签 git overriding cherry-pick git-cherry-pick

看,我在一个分支中进行了修改,然后从没有此修改的类似分支中选择一个提交。我想知道修改是否必须回滚。

最初,A 和 B 分支都拥有同一文件的完整副本

begin
 123
 456
 def f
 789
 klm
end

但是他们有分歧。首先,A 将 def f 移动到文件末尾,生成重构的 A

begin
 123
 456
 789
 klm
end
def f

现在,如果我们在 A 之上挑选 B,则原始文件将被恢复(def f 回到文件的中间)。这很好,因为我在得知 cherry-pick with -theirs produces an overriding alternative to cherry-pick 后就表示要问这个问题。 B 是文件的“他们的”版本,这正是我所期望的,因为我们看到 B 确实获胜:A 和 B 之间的唯一区别在于 A 重构的位置,在这种情况下,B 版本是首选。

然而,我开始问这个问题,因为情况并非总是如此。如果我们对 B 添加一些更改,例如将过程的第一行重写,例如将 123 重写为 222 (我在 bash 中将这个新版本的 B 标记为 C下面的代码)你认为将这个C选入A会产生什么结果?挑选A <- C的结果令人费解

begin
 222
 456
 789
 klm
end
def f

你看,第一行是来自C的222,但是def f也在最后,这意味着A的重构被保留了,而C没有覆盖它。在我看来,这是行为不一致的一个谜。您认为整个文件 B 与 A 不同,但一旦您进一步修改一点点,事实并非如此。不相关的更改会停止回滚,或者我只是无法弄清楚 git 规则。我应该在cherry-pick操作中期待哪些变化?

我认为 it is related situation 选择 B 表明整个文件已更改,而如果您选择修改后的 C,则 diff 会按照正常情况进行,仅检测单行更改。

您可以使用

重建情况
mkdir preserving ; cd preserving
git init ; echo rrr > root
git add root ; git commit -m root

git checkout -b B ; git checkout -b A

function makeABC {
    echo begin > abc
    echo " 123" >> abc
    echo " 456" >> abc
    echo " def f" >> abc
    echo " 789" >> abc
    echo " klm" >> abc
    echo end >> abc
}

echo commiting ABC into branch A
makeABC ; git add abc ; git commit -m abc

echo refactoring A, def f moved into the end of file
git checkout A
sed -i -e '/def f/d' abc
echo "def f" >> abc
git add abc ; git commit -m "refactoring 'def f'"

echo posting abc into B
git checkout B ; makeABC ; git add abc ; git commit -m "abc in B"

echo choosing which branch to pick
picking="B" ; case $picking in
    "B") ;;
    "C") git checkout -b C ; sed -i -e 's/123/CCC/g' abc
        git add abc ; git commit -m CCC ;;
esac

git checkout A ; git cherry-pick $picking -Xtheirs 

echo observe if refactoring def f is in place in A
gitk --all & 

echo 'preserving' folder created

picking变量的值设置为“B”或“C”以选择要在A上选取的分支。

最佳答案

这是因为 gitcherry-pick -Xtheirs-Xtheirs 部分仅说明如何处理冲突更改,并且有在上一个示例中,两次提交之间没有冲突的更改。 merge 策略是递归(本例中为默认策略),theirs 是此策略的一个选项。

如果有一个名为他们的策略,那么你就会得到你期望的结果。

现在,没有他们的策略,但是有一个我们的策略可以证明这一点。不要使用 gitcherry-pick -Xtheirs C ,而是尝试 gitcherry-pick --strategy=ours C ,看看会发生什么。它会有效地忽略来自 C 的更改,并表示无需提交任何内容。当然,这种策略在挑选时毫无用处,但可能有助于理解。

为了实现您最初真正想要的,这里有一种方法:

git checkout A
git read-tree -m -u C
git commit --no-edit -c C

有关 merge 策略的更多信息可以在 man git-merge 中找到。 .

关于git - 如果它们不同,为什么 gitcherry-pick 不覆盖当前分支中的修改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34187857/

相关文章:

git - 无法选择性提交更改不存在的文件

git - 如何在 ~/.ssh 目录中管理多个 ssh key

设置 SSH 后 Github 权限被拒绝(公钥)

java - Git merge/pull 后使用 Maven 进行部分全新安装

maven命令行如何为单个命令指向特定的settings.xml?

swift - 覆盖 Swift 子类中的属性

scala - 当您重写方法时,Scala 类中的指令顺序如何工作

mercurial - 使用 hg pull/push/merge/graft 将更改标记为已 merge 或故意忽略?

git - 如何重新 merge 已经 merge 的分支?

git - 如何在 bash 脚本中检查空的 cherry-picks?