
Moving on 👣
Moving on 👣 관련
Still, this was a simple case of a 3-way merge. John and Paul created different songs, so each of them touched a different file. It was pretty straightforward to execute the merge.
What about more interesting cases?
Let's assume that now John and Paul are co-authoring a new song.
So, John checkedout main
branch and started writing the song:
git checkout main

<Source: Brief>
He staged and committed it ("Commit 7"):

<Source: Brief>
Now, Paul branches:
git checkout -b paul_branch_2
And edits the song, adding another verse:

<Source: Brief>
Of course, in the original song, we don't have the title "Paul's Verse", but I'll add it here for simplicity.
Paul stages and commits the changes:
git add a_day_in_the_life.md
git commit -m "Commit 8"
John also branches out from main
and adds a few last lines:
git checkout main
git checkout -b john_branch_2

<Source Brief>
And he stages and commits his changes too ("Commit 9"):

<Source Brief>
This is the resulting history:

<Source Brief>
So, both Paul and John modified the same file on different branches. Will Git be successful in merging them? 🤔
Say now we don't go through main,
but John will try to merge Paul's new branch into his branch:
git merge paul_branch_2
Wait!! 🤚🏻 Don't run this command! Why would you let Git do all the hard work? You are trying to understand the process here.
So, first, Git needs to find the merge base. Can you see which commit that would be?
Correct, it would be the last commit on main
branch, where the two diverged.
You can verify that by using:
git merge-base john_branch_2 paul_branch_2

<Source Brief>
Great, now Git should compute the diffs and generate the patches. You can observe the diffs directly:
git diff main paul_branch_2

git diff main paul_branch_2
<Source Brief>
Will applying this patch succeed? Well, no problem, Git has all the context lines in place.
Ask Git to apply this patch:
git diff main paul_branch_2 > paul_branch_2.patch
git apply -–index paul_branch_2.patch
And this worked, no problem at all.
Now, compute the diff between John's new branch and the merge base. Notice that you haven't committed the applied changes, so john_branch_2
still points at the same commit as before, "Commit 9":
git diff main john_branch_2

git diff main john_branch_2
<Source Brief>
Will applying this diff work?
Well, indeed, yes. Notice that even though the line numbers have changed on the current version of the file, thanks to the context lines Git is able to locate where it needs to add these lines…

<Source Brief>
Save this patch and apply it then:
git diff main john_branch_2 > john_branch_2.patch
git apply –-index john_branch_2.patch

<Source Brief>
Observe the result file:

<Source Brief>
Cool, exactly what we wanted 👏🏻 You can now create the tree and relevant commit:
git write-tree
Don't forget to specify both parents:
git commit-tree -p paul_branch_2 -p john_branch_2 -m "Merging new changes"

<Source Brief>
See how I used the branches names here? After all, they are just pointers to the commits we want.
Cool, look at the log from the new commit:

<Source Brief>
Exactly what we wanted.
You can also let Git perform the job for you. You can simply checkout john_branch_2
, which you haven't moved – so it still points to the same commit as it did before the merge. So all you need to do is run:
git merge paul_branch_2
Observe the resulting history:

<Source: Brief>
Just as before, you have a merge commit pointing to "Commit 8" and "Commit 9" as its parents. "Commit 9" is the first parent since you merged into it.
But this was still quite simple… John and Paul worked on the same file, but on very different parts. You could also directly apply Paul's changes to John's branch. If you go back to John's branch before the merge:
git reset --hard HEAD~
And now apply Paul's changes:
git apply -–index paul_branch_2.patch

<Source: Brief>
You will get the same result.
But what happens when the two branches include changes on the same files, in the same locations? 🤔