In this video, we'll discuss resolving merge conflicts.
We will start with a merge conflict overview.
If you perform a merge with a merge commit,
Git takes on the responsibility of combining the work of
multiple branches and placing the result into a single merge commit.
Git will try to do this automatically.
However, there are cases where multiple branches
make different changes to the same part of a file.
In that case, a merge conflict occurs and
a person needs to make a decision on how to resolve it.
In this example, we start with commit A on the master branch.
That commit contains a fileA.txt file,
containing the string 'feature 1'.
Then, let's say that you create a 'feature 2' branch based on commit A.
While you are working on the 'feature 2' branch,
someone makes commit C on the master branch.
Commit C contains a fileA.txt file that
includes the string 'feature 3' as the second line of the file.
Now, let's say that you have finished 'feature 2' and
made a commit B on the 'feature 2' branch,
commit B contains a string 'feature 2' as the second line of the fileA.txt file.
Now, you are ready to merge your 'feature 2' work into the master branch.
You cannot use a fast forward merge because commit
C has been made to the master branch after you created the 'feature 2' branch.
When you perform a merge,
Git tries to automatically create a merge commit
combining the work of commits B and C. However,
when Git tries to combine the work,
it notices that the second line of fileA.txt is different on each branch.
Git doesn't know how to write fileA.txt and you have a merge conflict.
A person needs to decide how to write fileA.txt.
We have just seen that a merge conflict can occur if
different branches change the same part of a file in different ways.
If only one branch changes any file,
you'll not have a merge conflict.
In this example, the 'feature 2' branch adds a new file,
fileB.txt, to implement 'feature 2'.
There is no merge conflict because changes are made to separate files.
Commit C changed fileA.txt,
and commit B created fileB.txt after the merge,
commit M contains the two files implementing the three features.
Git also can automatically merge changes to different parts of the same file.
In Git, a part of a file is called a hunk.
In this example, the project starts with commit A which contains a
fileA.txt file containing 'feature 1' with a bug and 'feature 2'.
A 'feature 3' branch is created off of commit A of the master branch.
While the 'feature 3' branch is being worked on,
commit C is made which fixes the bug in 'feature 1'.
On the 'feature 3' branch,
the string 'feature 3' is appended to the fileA.txt file as commit B.
Notice that the 'feature 3' branch has the bug
because the bug was there when the branch was created.
When the 'feature 3' branch is finished,
a merge will execute without a merge conflict.
Git is smart enough to realize that
the first part of the file was changed on the master branch,
and the last part of the file was changed on the 'feature 3' branch.
In merge commit M,
Git will automatically create the fileA.txt file, shown here.
How Git actually merges the files depends on what is called, the merge strategy.
Usually, the default merge strategy works well.
Since Git is open source software,
anyone can contribute improved merge strategies.
There is a link to more information on merge strategies here.
We have seen that merge conflicts occur when
two branches modify the same hunk of the same file.
To make merging easier,
avoid making a lot of changes over a long period of time without merging.
Smaller frequent mergers are usually the best approach.
It's better to create many small merge problems than one giant merge problem.
The diagram on the left shows what to avoid with Git.
A branch was made off of the initial commit and then
more branches and commits were made without merging back into the master branch.
Notice that the master branch has been changing as we've been working.
It's better to frequently merge,
as shown in the diagram on the right.
If your project is a software project,
decoupled modular code is much less likely to have merged conflicts.
In some ways, the number and complexity of merge conflicts is a test
of how modular your code is.
Next, we will discuss resolving a merge conflict.
Resolving a merge conflict between two branches involves three commits.
Let's look at a simple example to help understand these three commits.
In this commit graph,
the project starts with commit A on the master branch,
a 'feature X' branch was created off of commit A.
Commit B was then made to the master branch,
then commit C was made to the 'feature X' branch.
Let's assume that we are finished with 'feature X' and
want to merge it into the master branch,
we've checked out the master branch,
as you can see from the head reference pointing to the master branch label.
The first commit involved with resolving
a merge conflict is the commit at the tip of the current branch.
We call this commit, ours or mine.
In our example, the current branch is the master branch and the tip is commit B.
The second commit involved with resolving emerge conflict is
the commit at the tip of the branch to be merged.
We call this commit, theirs.
In our example, the branch to be merged is the 'feature X' branch and the tip is commit
C. The final commit involved with resolving
a two-branch merge conflict is the common ancestor of the two branches.
We call this commit, the merge base.
In our example, the most recent commit that both branches contain is commit A,
so commit A is our merge base.
Here are the basic steps to resolve a merge conflict.
You start out just like with any other merge by checking out the base branch.
In this case, the base branch is the master branch.
You then attempt to merge the 'feature X' branch into the master branch.
Git will inform you that there is a merge conflict,
both branches modified the same hunk in fileA.txt in different ways.
At this point, Git has modified fileA.txt,
showing you exactly where the conflicts are,
and has placed the file in your working tree.
You then open fileA.txt and resolved the merge conflict.
This is the part that requires human judgment.
Once fileA.txt looks the way that you want it to,
you stage it so that it becomes part of the merge commit.
You then commit the merge.
At this point, the branches are merged.
Just like with other merges,
you can then optionally delete the 'feature X' branch label.
The key point here is that,
when attempting a merge,
files with conflicts are modified by Git and placed in the working tree.
You need to fix those files before executing a successful merge.
Let's take a look at a merge conflict.
In fileA.txt, we have intentionally modified
the same hunk in both branches so that a merge will result in a conflict.
We see here that our starting commit graph has three commits.
The original commit added 'feature 1'.
A 'feature 2' branch was made off of the original commit,
and the commit was made to that branch.
The current commit on the master branch added 'feature 3'.
We have checked out the master branch,
as you can see from the head reference.
We then try to merge in the 'feature 2' branch.
You can see that Git tried automatically to perform
a merge but ran into a conflict in fileA.txt.
Git saw that we had modified the same hunk in conflicting ways on the two branches.
You are asked to fix the conflicts and then commit the result.
You have to fix the merge conflict before you can execute a successful merge.
We then execute the Git status command to view information
on the conflicted files that Git has placed in the working tree.
The messages tell you that you have tried to merge but have unmerged paths.
It tells you to fix and commit fileA.txt.
Another option it mentions is to use the abort flag to abort this merge attempt.
You can see that Git messages are very helpful.
Next, we will have to fix the conflicted fileA.txt.
You can use any editor that you want to fix the conflicted file.
This can be a simple text editor,
or a custom tool called a diff or merge tool.
We'll keep it simple here and use a simple text editor.
When you view fileA.txt,
you can see that Git marked up the file in hunks where there are conflicts.
Conflicted hunks are surrounded by less than and
greater than signs that are called, conflict markers.
This file has one conflicted hunk immediately after the 'feature one line.
Any text that isn't surrounded by conflict markers was cleanly resolved by Git.
The first part of the conflict marker is labeled head.
We have checked out the master branch,
so this line is from the file in the master branch.
This is the ours commit in the merge.
After the equal signs is the line 'feature 2'.
This is labeled with the branch name,
so this line comes from the 'feature 2' branch.
This is that theirs commit in the merge.
So basically, what happened is that,
Git saw these changes and didn't know what line to a fileA.txt should say.
Should it say 'feature 3',
or should it say 'feature 2'?
That's why the merge conflict was presented,
Git needed a human to make a decision.
We can use our text editor to fix fileA.txt.
We have ordered the features nicely in a file.
This file will be part of the merge commit.
Now that we have fixed fileA.txt,
we can add it to the stage and commit the merge.
Let's start by viewing our fixed fileA.txt.
The features are in the correct order.
Next, we use the Git add command to add fileA.txt to the staging area.
Then, we execute Git commit.
Your default Git editor will appear with a default commit message.
Edit that message if desired.
The commit is then executed successfully,
and the branches are merged.
We can then view the commit graph and verify that the merge executed as expected.
Our current commit on the master branch contains all three features.
We can then optionally delete the 'feature 2' branch
since the master branch contains all of the commits.
Our merge is complete.
Here's a review of what we've discussed in this video.
Merge conflicts occur when two branches modified the same hunk.
When a conflict occurs,
Git will create files in the working tree containing conflict markers,
fix, add, and commit the conflicted files.
Now, it's time for you to work on the topics discussed in this video.
Separate instructions are provided for you.