看,我在一个分支中进行了修改,然后从没有此修改的类似分支中选择一个提交。我想知道修改是否必须回滚。
最初,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/