问题
Updated
Consider file abc, identical in both commits A and B
begin
123
456
789
klm
end
In A, we refactor first line 123 => AAA
and pick B on top of the result. Git tells that all lines in the file have changed
. Its diff will operate normally however, if we modify B by updating any single line. Git will notice that only this one line of text has changed in this case, reporting a single-line conflict if it was the first line also.
Here is the code to reproduce
mkdir full-shit ; cd full-shit
git init ; echo rrr > root ; git add root
git commit -m root
git checkout -b A ; git checkout -b B
function makeABC {
echo begin > abc
echo " 123" >> abc
echo " 456" >> abc
echo " 789" >> abc
echo " klm" >> abc
echo end >> abc
}
echo commiting ABC into branch B
makeABC ; git add abc ; git commit -m abc
echo will make a new file for A instead of 'git cherry-pick B'
git checkout A ; makeABC
echo 'git checkout A ; git cherry-pick B' would work equally well to make copy A = B
sed -i -e 's/123/AAA/g' abc
git add abc ; git commit -m "A refactored"
echo observe that !!!PICKING B TELLS THAT ALL LINES BETWEEN A AND B ARE DIFFERENT!!!
echo whereas if we picked C instead of B this would not happen -- git would make the diff operation properly, detectinc collision at the frist line of abc
case "B" in
"B") git cherry-pick B ;;
"B2") git checkout B
sed -i -e 's/123/BBB/g' abc
git add abc ; git commit -m BBB
git checkout A ; git cherry-pick B ;;
esac
git gui &
echo 'full-shit' folder created
Please note that Git Gui marked all lines as conflicting whereas EOL characters totally match in both commits because they were created in the same run, by the same code and you can even use cherry-pick from B to A to avoid file system operations for exact copy.
For this reason, I believe, this issue is more related to the previous one, than to the EOL, which often causes a similar result. Likewise in that case, git starts to differentiate single lines if I add B2 change on top of first commit in B. What is the logic of git?
回答1:
This sometimes happens if you change the newline type (Windows newline vs Unix newline). git can show diff ignoring whitespace changes.
回答2:
When you select a commit in the git-gui
history browser, it is showing what changed between that commit and its first parent, in this case the same output as git diff A^..A
. Since branch A
did not have this file until in its last commit, the diff naturally shows the whole file as new. B
is not even considered at this point.
When you diff the two branch heads (git diff A..B
) you will see the direct difference between A
and B
regardless of the histories of the two.
More information on the syntax used for git diff
above may be found in man git-revisions.
As for the cherry-pick, it gets it right thanks to three-way merge.
来源:https://stackoverflow.com/questions/34189779/why-does-cherry-pick-tell-me-that-i-have-all-lines-changed