0

With the following sequence of commands:

#!/bin/bash

git init

# Below is first commit
touch a.txt
echo "first commit in a" > a.txt
git add a.txt
touch b.txt
echo "first commit in b" > b.txt
git add b.txt
git commit -m "first commit"

# below is second linear commit
echo "second main change to a in master" > a.txt
echo "second main change to b in master" > b.txt
git add a.txt b.txt
git commit -m "second commit"

# create branch from first 
git checkout -b branch_for_a HEAD~1

I am setup like so:

enter image description here

So, at present HEAD = branch_for_a and HEAD and master are completely different in that both a.txt and b.txt are changed between the two commits.

When I now issue: git cherry-pick master, I would expect that I would have to resolve merge conflicts for both a.txt as well as b.txt. However, git replaces my working directory with the a.txt and b.txt from master with no requirement to resolve the conflict. I would like to understand why this is so.


However, instead of issuing git cherry-pick master, if I instead create a new commit with changed a.txt and b.txt onward from branch_for_a like so:

echo "branch a" > a.txt
echo "branch b" > b.txt
git add a.txt b.txt
git commit -m "branch commit"

I am in this situation now:

enter image description here

If I issue git cherry-pick master now, git indicates that I have to resolve merge conflicts in a.txt and b.txt which I can understand as correct.


I am unable to understand why no merge conflicts were required to be resolved in the first case.

Tryer
  • 3,580
  • 1
  • 26
  • 49
  • 1
    In the first case git knew you were just applying the modifications found from first to second commit. In the second there were no "known" modifications from second to "branch commit" – Ivan Dec 21 '22 at 15:38
  • 1. Why do you expect conflicts when the files are not changed in the new branch? – 273K Dec 21 '22 at 15:38
  • @273K My understanding (which is obviously in need of refinement) was that in the first case, just as in the second case, the files in my working directory are different from the commit I am cherry picking from, `master` in both cases. – Tryer Dec 21 '22 at 16:08

1 Answers1

3

For context, when you cherry-pick a commit and get a conflict, it's because you are attempting to "merge" that commit by itself.

In the first case, no merge is necessary at all because master is already exactly in the position you're trying to place it. In other words, if you have branch_for_a checked out, the following commands would result in the identical state afterwards:

  1. git merge master
  2. git cherry-pick master

Using cherry-pick in this instance will still rewrite the commit and change the ID, but it's not possible to have a merge conflict because the commit you are picking already has branch_for_a as its parent.

In order to have a conflict, the commits must have different parents, and the changes to the file must overlap near the same lines of the file. In the second example both of those conditions were met. A more detailed explanation can be found here.

TTT
  • 22,611
  • 8
  • 63
  • 69
  • Thank you. On `branch_for_a` I would like to work with `master`'s `b.txt` with no further changes to it, but modifying `first commit`'s `a.txt`. That is why I created a branch at `first commit`. It seems that the only way to get that state in my working directory would be to make a "spurious" change to `b.txt`, commit that change on `branch_for_a` and then from this new commit issue `git cherry-pick master` and choose to resolve the merge conflict by applying all changes from `master`'s `b.txt` This seems like a roundabout way. Is there any simpler way to achieve this? – Tryer Dec 21 '22 at 15:55
  • 1
    @Tryer Some commands, including `cherry-pick` and `merge`, have an option called `--no-commit` which pauses before creating the commit. At this point you'd have both files staged, and you could then unstage and/or modify and re-stage files to modify the commit however you'd like, and then commit it. (And Git offers a `git cherry-pick --continue` or `git merge --continue` option as well if you don't want to commit it manually.) **However**, if you're cherry-picking from a shared branch like `master`, this greatly increases the chances of a conflict when you merge into `master` later. – TTT Dec 21 '22 at 17:02
  • 1
    To clarify the last sentence of my previous comment, cherry-picking a commit from a shared branch, *and also editing* that commit before committing it, is likely to cause a conflict when merging into the shared branch later. Cherry-picking by itself doesn't (greatly) increase the chances of a conflict. – TTT Dec 21 '22 at 17:22