为什么不在当前分支git樱桃选择覆盖修改,如果他们是不同的? [英] Why doesn't git cherry-pick override modification in current branch if their is different?

查看:144
本文介绍了为什么不在当前分支git樱桃选择覆盖修改,如果他们是不同的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  begin 
123
456
def f
789
klm
end

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

  begin 
123
456
789
klm
end
def f
def f 返回在文件的中间)。这很好,因为我曾经告诉过这个问题,一旦我被告知樱桃选择与 - 他们产生一个压倒一切的替代方案。 B是文件的'他们'版本,这是我所期望的,因为我们看到B确实赢了:A和B之间的唯一区别在于A重构,B版本在这种情况下是首选。

然而我开始提出这个问题,因为事情并非总是如此。如果我们给B添加一点变化,例如重写过程的第一行,例如123,至 222 (我标记这个新版本的B C 在下面的bash代码中),你认为选择C到A的结果是什么? A< C的挑选结果令人费解

  begin 
222
456
789
klm
end
def f

你看,第一行是C中的222,但是 def f 也是最后一行,这意味着A的重构已经保存,C没有重写它。这是IMO不一致行为的一个谜。你认为B与整个文件不同,但它不是,一旦你进一步修改一点点。无关的变化阻止了回滚,或者我无法弄清楚git规则。我应该在樱桃挑选期间做出哪些改变?



我认为它是相关情况,其中选择B表示整个文件已经改变,而如果你选择修改后的C,则diff正常情况下只检测到单行更改。您可以重构使用的情况

  mkdir保存; cd保存
git init; echo rrr> root
git add root; git commit -m root

git checkout -b B; git checkout -b A

函数makeABC {
echo begin> abc
echo123>> abc
echo456>> abc
echodef f>> abc
echo789>> abc
echoklm>> abc
echo end>> abc
}

将ABC提交到分支A
makeABC; git add abc; git commit -m abc

echo重构A,def f移动到文件末尾
git checkout A
sed -i -e'/ def f / d'abc
echodef f>> abc
git add abc; git commit -mrefactoring'def f'

echo将abc写入B
git checkout B; makeABC; git add abc; git commit -mB中的abc

回显选择哪个分支选择
picking =B;
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

回声观察重构def f是否在A
位置gitk --all&

echo'preserving'文件夹已创建

设置<$ c $的值c>选择变量为B或C来选择您希望在A上选择的分支。

解决方案

这是因为 git cherry-pick -Xtheirs -Xtheirs 部分只说明使用冲突更改,并且在上次示例中的两次提交之间没有冲突的更改。合并策略是递归(本例中为默认值),他们的是此策略的一个选项。 p>

如果有策略叫做他们的,那么你会得到你的结果预计。



现在,没有他们的策略,但是有一个我们的策略可以证明这一点。而不是 git cherry-pick -Xtheirs C ,请尝试 git cherry-pick --strategy =我们的C 并查看内容发生。它会有效地忽略来自 C 的变化,并说没有什么可提交的。这种策略在挑选樱桃时当然是无用的,但它可能有助于理解。



为了达到你真正想要的东西,这里有一种方法可以做到它:

  git checkout A 
git读取树-m -u C
git commit - no-edit -c C

有关合并策略的更多信息可以在 man git-merge


Look, I make a modification in a branch and then pick a commit from a similar branch, which does not have this modification. I wonder if modification must be rolled back or not.

Initially, both A and B branches have a full copy of the same file

begin
 123
 456
 def f
 789
 klm
end

But they diverge. First, A moves def f into the end of file, producing refactored A

begin
 123
 456
 789
 klm
end
def f

Now, if we cherry-pick B on top of this A, the original file is recovered (def f is back in the middle of the file). This is fine because I stated to ask this question once I was informed that cherry-pick with -theirs produces an overriding alternative to cherry-pick. B is 'their' version of the file and it is what I expected because we see that B wins indeed: the only difference between A and B is in the place of A-refactoring and B version is preferred in this case.

I however started to ask this question because it is not always the case. If we add a bit of change to B, e.g rewrite the first line of the procedure for instance, 123 to 222 (I label this new version of B C in the bash code below) what will be the result of picking this C into A do you think? The result of picking A <- C is puzzling

begin
 222
 456
 789
 klm
end
def f

You see, the first line is 222 from C but def f is also in the end, which means that refactoring of A has preserved and C did not override it. That is a mystery of inconsistent behaviour IMO. You think that B is different from A by the whole file but it is not, once you further modify a little bit. The unrelated change stop the rollback or I just cannot figure out the git rules out. Which changes should I expect in the cherry-pick op?

I think that it is related situation where picking B tells that whole file has changed whereas if you pick modified C, diff proceeds per normal detecting only single line change.

You can reconstruct the situation using

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

Set value of picking variable to "B" or "C" to choose the branch that you want to pick upon A.

解决方案

This is because the -Xtheirs part of git cherry-pick -Xtheirs only says what to do with conflicting changes, and there are no conflicting changes between the two commits in your last example. The merge strategy is recursive (the default in this case), and theirs is an option to this strategy.

If there was a strategy called theirs, then you would have gotten the result which you expected.

Now, there is no theirs strategy, but there is an ours strategy that can demonstrate the point. Instead of git cherry-pick -Xtheirs C, try git cherry-pick --strategy=ours C and see what happens. It will effectively ignore the changes from C and say that there is nothing to commit. This strategy is of course useless when cherry-picking, but it may help to understand.

To achieve what you really wanted in the first place, here is one way to do it:

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

More information about merge strategies can be found in man git-merge.

这篇关于为什么不在当前分支git樱桃选择覆盖修改,如果他们是不同的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆