Merging - with conflict
Let's practice another merge, but now with a change that conflicts.
But first, read up a little on what causes merge conflicts.
Create and checkout a new alsoMyBranch
, but start it from the same point where main
started, by providing a sha as an additional argument. You can use several methods to refer to that point. Assuming your graph has this topology...
* 686e8db (HEAD -> main) merge HTML source menu updates in index.html and help.html
|\
| * ccaf82c (mybranch) each menu item on a separate line in the code
* | f7295ef each menu item on a separate line in the code (for help.html)
|/
* 2dd739a (origin/main) Some handy git aliases, and an initial .gitignore
* 4ca41a7 Initial commit
...the following notations all resolve to the same commit:
main^^
- two commits before mainHEAD^^
- two commits before HEADorigin/main
- the commit on which theorigin/main
tracking branch sits2dd739a
- the shortname of the commit2dd7
- an even shorter name--works as long as it's unambiguous in the repo2dd739a539c6cc30e9b3cdfa952439ba93c0c392
- the full SHA
git checkout -b alsoMyBranch main^^ # Each caret (^) goes back one commit
Now alsoMyBranch
exists and sits on 2dd739a
, and HEAD
is pointing to it; that is, it's your current branch.
Change the menu item source code in index.html
like you did on mybranch
--but not exactly like you did; let's add another menu item to index.html
.
From this...
<a href="./index.html">Home</a> <a href="./help.html">Help</a>
... to this:
<a href="./index.html">Home</a>
<a href="./map.html">Map</a>
<a href="./help.html">Help</a>
Save the file. Now git add
and git commit
...
adog # Check how the graph looks.
git diff # What am I about to add to the index?
git add index.html
adog # Check how the graph looks. Has it changed?
git diff --staged # What am I about to commit to git?
git diff # Why does this show no differences?
git commit -m "add 'Map' to the menu"
adog # Check how the graph looks. How about now?
The git graph should now look something like this:
adog
* daf0eb2 (HEAD -> alsoMyBranch) add 'Map' to the menu
| * 686e8db (main) merge HTML source menu updates in index.html and help.html
| |\
| | * ccaf82c (mybranch) each menu item on a separate line in the code
| |/
|/|
| * f7295ef each menu item on a separate line in the code (for help.html)
|/
* 2dd739a (origin/main) Some handy git aliases, and an initial .gitignore
* 4ca41a7 Initial commit
Let's merge!
git merge mybranch # Merge mybranch into current branch
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
There it is--the merge conflict. Git doesn't have enough info to know what you want to happen.
At this point, git has placed annotations about the conflict into index.html
, and left it up to you to figure it out. You can view the contents of the file directly, like this:
cat index.html
<html>
<head>
<title>Solar System</title>
</head>
<body>
<h1>The Solar System</h1>
<a href="./index.html">Home</a>
<<<<<<< HEAD
<a href="./map.html">Map</a>
=======
>>>>>>> mybranch
<a href="./help.html">Help</a>
<h1>Hello World!</h1>
</body>
</html>
The changes from your current branch show up between <<<<<<< HEAD
and =======
.
The changes from the merged-in mybranch
show up between =======
and >>>>>>> mybranch
.
You can use VSCode to view index.html
; VSCode understands the merge-conflict format and decorates your conflict with buttons to help out.
In this case, you would want both changes: the new map.html
link, and the help.html
link on a line by itself (which in this case, somewhat non-intuitively, shows up as an empty diff for the merged-in branch).
Click Accept Both Changes
in VSCode, or manually delete the >>>>>>>
, <<<<<<<
, and =======
delimiters that git added, so that the code looks like this:
<html>
<head>
<title>Solar System</title>
</head>
<body>
<h1>The Solar System</h1>
<a href="./index.html">Home</a>
<a href="./map.html">Map</a>
<a href="./help.html">Help</a>
<h1>Hello World!</h1>
</body>
</html>
Now, inform git of your resolution decision by git add
'ing the file that had the conflict:
git add index.html
And finally, commit it. Git remembers you're still merging, so will make this commit a merge commit--that is, a commit with two parents.
git commit -m "merge 'Map' entry with mybranch"
Key Takeaways:
- You can start a branch from any commit--not necessarily the one you happen to be on.
- You can reference a commit in lots of different ways.
- By definition, merge commits have two or more parents.
- The changes for the branch you're on will show up first in a merge conflict's diff report.
- The changes for the branch being merged into your current branch will show up last in a merge conflict's diff report.
- NOTE: A given merge may have more than one set of conflicts to resolve, even within the same file. Don't assume the first conflict is the only one!