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.