341 lines
10 KiB
Plaintext
341 lines
10 KiB
Plaintext
gitmergeconflicts(7)
|
|
====================
|
|
|
|
NAME
|
|
----
|
|
gitmergeconflicts - Guide to handling merge conflicts
|
|
|
|
DESCRIPTION
|
|
-----------
|
|
|
|
Merge conflicts can happen during a `git merge`, `git rebase`, `git
|
|
cherry-pick`, `git pull`, `git revert`, or any other command that does
|
|
a merge. All of those commands use the same merge algorithm, and the
|
|
process for resolving a merge conflict is always very similar.
|
|
|
|
There are 3 ways to handle a merge conflict:
|
|
|
|
* Resolve the conflict. (see <<resolve,HOW TO RESOLVE A MERGE CONFLICT>>
|
|
below for details)
|
|
* Stop the operation and return your branch to its original state
|
|
with the appropriate `--abort` command, for example `git merge --abort`
|
|
or `git rebase --abort`. See <<git_status,EXAMPLE: GIT STATUS OUTPUT>> below
|
|
for how to find the command to run.
|
|
* Or (if you're in a multi-step rebase or cherry-pick) skip the problematic
|
|
commit with the appropriate `--skip` command
|
|
|
|
WHAT IS A MERGE CONFLICT?
|
|
-------------------------
|
|
|
|
When Git merges two commits together, it looks at the changes that
|
|
each side has made and combines those changes. For example, if one side
|
|
edited lines 1-5 of `hello.py` and the other side edited lines 20-25 of
|
|
the same file, then it can easily combine them since there's no overlap.
|
|
|
|
But if both sides edited overlapping lines of the same file (for example
|
|
one side edited lines 1-5 and the other edited lines 3-6), Git will
|
|
not try to guess how to combine those changes. This is called a "merge
|
|
conflict".
|
|
|
|
When this happens, Git shows you both sides' edits and asks you to pick
|
|
how to resolve them. It:
|
|
|
|
* Stages all of the files which were successfully merged
|
|
* For the files with conflicts, it marks them as conflicted, puts both
|
|
sides' edits in the file, and leaves <<markers, merge conflict markers>>
|
|
that you need to resolve.
|
|
|
|
[NOTE]
|
|
================================
|
|
Even if Git successfully merges both sides with no conflicts, it's
|
|
possible to end up with code that doesn't work. For example, this can
|
|
happen if one side renames a function, and the other side adds a call to
|
|
the old function. This is called a "semantic merge conflict".
|
|
================================
|
|
|
|
[[markers]]
|
|
MERGE CONFLICT MARKERS
|
|
----------------------
|
|
|
|
When there's a merge conflict, Git will update the conflicted file
|
|
to include merge conflict markers `<<<<<<<`, `=======`, and `>>>>>>>`.
|
|
For example, here's a merge conflict where both sides edited a list of
|
|
fruits in different ways, and ended up in different states. One side
|
|
has "banana" but not "cherry", and the other side has "cherry", but
|
|
not "banana".
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
<<<<<<< HEAD
|
|
"cherry",
|
|
=======
|
|
"banana",
|
|
>>>>>>> add-fruit
|
|
"mango",
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
The lines from one side of the merge conflict are between `<<<<<<<` and
|
|
`=======`, and the lines from the other side are between `=======` and
|
|
`>>>>>>>`. See <<ours,"OURS" AND "THEIRS">> below for a full explanation
|
|
of which side is which.
|
|
|
|
|
|
[[resolve]]
|
|
HOW TO RESOLVE A MERGE CONFLICT
|
|
-------------------------------
|
|
|
|
The process for resolving a merge conflict is:
|
|
|
|
1. Run `git status` to get a list of files with merge conflicts
|
|
2. For each one, find the conflict markers
|
|
(the `<<<<<<<`, `=======`, `>>>>>>>`) and edit the code to
|
|
fix the conflict
|
|
3. Run `git add FILENAME` for each file to mark the conflict as resolved
|
|
4. Run the appropriate `--continue` command to continue the operation
|
|
that was interrupted by the conflict, for example `git merge --continue`
|
|
or `git rebase --continue`. See <<git_status,EXAMPLE: GIT STATUS OUTPUT>>
|
|
below for how to find the command to run.
|
|
+
|
|
Note: During a `git merge`, `git commit` and `git merge --continue` do
|
|
the same thing.
|
|
|
|
|
|
[[example]]
|
|
EXAMPLE OF RESOLVING A MERGE CONFLICT
|
|
-------------------------------------
|
|
|
|
If you see this in your code during a merge conflict:
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
<<<<<<< HEAD
|
|
"cherry",
|
|
=======
|
|
"banana",
|
|
>>>>>>> add-fruit
|
|
"mango",
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
Then you might edit that part of the code like this, to take
|
|
all the fruits from both sides of the conflict:
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
"banana",
|
|
"cherry",
|
|
"mango",
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
|
|
[[tools]]
|
|
TOOLS FOR HANDLING MERGE CONFLICTS
|
|
----------------------------------
|
|
|
|
Here are some ways to get extra context while handling a merge conflict:
|
|
|
|
* There are many graphical "merge tools" for Git, which will normally
|
|
show you the different versions of the code side by side.
|
|
If you have a mergetool configured, `git mergetool` will launch it.
|
|
See also `merge.tool` in linkgit:git-config[1] for a list of
|
|
the mergetools Git supports.
|
|
|
|
* You can set the configuration variable `merge.conflictstyle=diff3`.
|
|
See <<diff3,DIFF3>> below for more.
|
|
|
|
* `git log --merge -p <filename>` will list all commits which
|
|
caused the merge conflict for `<filename>`, and the diff
|
|
of how they changed the file.
|
|
|
|
* Look at the original files. `git show :1:filename` shows the
|
|
common ancestor, `git show :2:filename` shows the "ours"
|
|
version, and `git show :3:filename` shows the "theirs"
|
|
version. See <<ours,"OURS" AND "THEIRS">> below for more on
|
|
"ours" and "theirs".
|
|
|
|
Here are some ways to track your progress while handling a conflict:
|
|
|
|
* Use `git status` to get a list of files with conflicts
|
|
|
|
* Use `git diff --check` to make sure you haven't left any merge
|
|
conflict markers in a file by accident. It will print "leftover
|
|
conflict marker" if it finds any.
|
|
|
|
* Use `git diff AUTO_MERGE` to show what changes you've made so far to
|
|
resolve the conflicts.
|
|
See <<automerge,EXAMPLE OF USING `AUTO_MERGE`>> below for more.
|
|
|
|
[[git_status]]
|
|
EXAMPLE: GIT STATUS OUTPUT
|
|
--------------------------
|
|
|
|
When you're in a merge conflict, you can find out what commands to run
|
|
to handle the conflict by running `git status`.
|
|
|
|
For example, this `git status` output tells you that:
|
|
|
|
* `git rebase --abort` will safely bring your branch back to its
|
|
original state
|
|
* you should run `git rebase --continue` when you're done resolving all
|
|
the conflicts
|
|
* the conflicts in `fruits.py` haven't been marked as resolved
|
|
|
|
----
|
|
$ git status
|
|
You are currently rebasing branch 'main' on '58a9fcc'.
|
|
(fix conflicts and then run "git rebase --continue")
|
|
(use "git rebase --skip" to skip this patch)
|
|
(use "git rebase --abort" to check out the original branch)
|
|
|
|
Unmerged paths:
|
|
(use "git restore --staged <file>..." to unstage)
|
|
(use "git add <file>..." to mark resolution)
|
|
both modified: fruits.py
|
|
----
|
|
|
|
|
|
[[diff3]]
|
|
DIFF3
|
|
-----
|
|
|
|
By default, Git doesn't include the original code when formatting
|
|
a merge conflict. To include the original code, you can set the
|
|
configuration option `merge.conflictstyle` to `diff3`.
|
|
This extra context can make it easier to understand what's
|
|
happening in a merge conflict and avoid mismerges.
|
|
|
|
Here's an example of what a merge conflict would look like when using
|
|
`diff3`. There's an extra section (between `|||||||` and `=======`)
|
|
with the original code.
|
|
|
|
With this view, you can see that both sides fixed a spelling
|
|
mistake in "mango", and each removed one fruit from the list.
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
<<<<<<< HEAD
|
|
"cherry",
|
|
"mango",
|
|
||||||| 1c22e48
|
|
"banana",
|
|
"cherry",
|
|
"mangoooo",
|
|
=======
|
|
"mango",
|
|
>>>>>>> add-fruit
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
In the default format, you would see this conflict as shown before,
|
|
i.e., "one side has 'banana', the other side has 'cherry', everything
|
|
else is the same". But presented this way, we would realize that the
|
|
conflict resolution to keep "banana" and "cherry" we showed earlier
|
|
was incorrect. Rather, we want to drop "banana", and "cherry" and
|
|
keep the "mango" with corrected spellings. The `diff3` format is more
|
|
unambiguous by being more verbose.
|
|
|
|
[NOTE]
|
|
================================
|
|
`zdiff3` is an alternative to `diff3` that makes the merge conflict
|
|
shorter by making it more ambiguous.
|
|
================================
|
|
|
|
[[ours]]
|
|
"OURS" AND "THEIRS"
|
|
-------------------
|
|
|
|
Sometimes during a merge conflict, Git will use the terms "ours" and
|
|
"theirs" (or "us" and "them"). For example, `git status` might say that
|
|
a file was `deleted by us`.
|
|
|
|
"Ours" and "theirs" are both commits: "ours" is the current
|
|
`HEAD` commit, and "theirs" is the other side being merged.
|
|
|
|
The first part of a merge conflict (between `<<<<<<<` and `=======`) is
|
|
from the "ours" side, and the second part (between `=======` and
|
|
`>>>>>>>`) is from the "theirs" side.
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
<<<<<<< HEAD
|
|
"cherry", <- ours
|
|
=======
|
|
"banana", <- theirs
|
|
>>>>>>> add-fruit
|
|
"mango",
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
During a rebase, it can seem "upside down" because the "ours" commit is
|
|
from the branch you're rebasing on (for instance `main` in `git rebase
|
|
main`).
|
|
|
|
These terms in Git all mean the same thing when dealing with a merge
|
|
conflict:
|
|
|
|
* "common ancestor" and "base". The files from this commit are "in stage 1".
|
|
* "ours", "us", and `HEAD`. The files from this commit are "in stage 2".
|
|
* "theirs", "them". The files from this commit are "in stage 3".
|
|
|
|
If you're confused about what something like "deleted by us" means, it's
|
|
often easiest to use some of the tools from
|
|
<<tools,TOOLS FOR HANDLING MERGE CONFLICTS>> above to get more context.
|
|
Finding the commit that deleted the file and seeing why is usually more
|
|
helpful than trying to abstractly reason through what "us" means.
|
|
|
|
[[automerge]]
|
|
EXAMPLE OF USING `AUTO_MERGE`
|
|
-----------------------------
|
|
|
|
`git diff AUTO_MERGE` will show what changes you've made so far to
|
|
resolve conflicts. `AUTO_MERGE` is a reference that Git creates during a
|
|
merge. It contains the result of running the merge algorithm.
|
|
|
|
For example, if we resolved the conflict by adding both "banana" and
|
|
"cherry" in order, the diff would look like this:
|
|
|
|
----
|
|
FRUITS = [
|
|
"apple",
|
|
-<<<<<<< HEAD
|
|
- "cherry",
|
|
-=======
|
|
"banana",
|
|
->>>>>>> add-fruit
|
|
+ "cherry",
|
|
"mango",
|
|
"orange",
|
|
]
|
|
----
|
|
|
|
[NOTE]
|
|
`AUTO_MERGE` is only set if you're using the default Git merge algorithm.
|
|
|
|
|
|
SEE ALSO
|
|
--------
|
|
|
|
linkgit:git-revert[1]
|
|
linkgit:git-merge[1]
|
|
linkgit:git-rebase[1]
|
|
linkgit:git-cherry-pick[1]
|
|
linkgit:git-pull[1]
|
|
linkgit:git-diff[1]
|
|
|
|
GIT
|
|
---
|
|
|
|
Part of the linkgit:git[1] suite
|