Merge branch 'je/doc-merge-conflicts' into seen

A new user manual page on how to resolve merge conflicts has been
introduced, and other commands that could encounter conflicts have
been updated to link to it.

* je/doc-merge-conflicts:
  SQUASH???
  doc: git-pull: link to new merge conflicts guide
  doc: git-cherry-pick: link to new merge conflicts guide
  doc: git-revert: link to new merge conflicts guide
  doc: git-rebase: link to new merge conflicts guide
  doc: git-merge: link to new merge conflicts guide
  doc: add new gitmergeconflicts man page
seen
Junio C Hamano 2026-10-12 13:00:05 -07:00
commit 6d9ab1893b
10 changed files with 367 additions and 131 deletions

1
.gitattributes vendored
View File

@ -14,6 +14,7 @@ CODE_OF_CONDUCT.md -whitespace
/t/oid-info/* text eol=lf
/Documentation/git-merge.adoc conflict-marker-size=32
/Documentation/git-merge-file.adoc conflict-marker-size=32
/Documentation/gitmergeconflicts.adoc conflict-marker-size=32
/Documentation/gitk.adoc conflict-marker-size=32
/Documentation/user-manual.adoc conflict-marker-size=32
/t/t????-*.sh conflict-marker-size=32

View File

@ -59,6 +59,7 @@ MAN7_TXT += gitdiffcore.adoc
MAN7_TXT += giteveryday.adoc
MAN7_TXT += gitfaq.adoc
MAN7_TXT += gitglossary.adoc
MAN7_TXT += gitmergeconflicts.adoc
MAN7_TXT += gitpacking.adoc
MAN7_TXT += gitnamespaces.adoc
MAN7_TXT += gitremote-helpers.adoc

View File

@ -19,8 +19,7 @@ Given one or more existing commits, apply the change each one
introduces, recording a new commit for each. This requires your
working tree to be clean (no modifications from the HEAD commit).

When it is not obvious how to apply a change, the following
happens:
When a merge conflict happens:

1. The current branch and `HEAD` pointer stay at the last commit
successfully made.
@ -36,8 +35,8 @@ happens:
conflict markers `<<<<<<<` and `>>>>>>>`.
5. No other modifications are made.

See linkgit:git-merge[1] for some hints on resolving such
conflicts.
See linkgit:gitmergeconflicts[7] (or `git help mergeconflicts`)
for a guide to handling merge conflicts.

OPTIONS
-------
@ -259,6 +258,7 @@ $ git cherry-pick -Xpatience topic^ <4>
SEE ALSO
--------
linkgit:git-revert[1]
linkgit:gitmergeconflicts[7]

GIT
---

View File

@ -49,7 +49,8 @@ a log message from the user describing the changes. Before the operation,
A merge stops if there's a conflict that cannot be resolved
automatically or if `--no-commit` was provided when initiating the
merge. At that point you can run `git merge --abort` or `git merge
--continue`.
--continue`. See linkgit:gitmergeconflicts[7]
(or `git help mergeconflicts`) for a guide to handling merge conflicts.

`git merge --abort` will abort the merge process and try to reconstruct
the pre-merge state. However, if there were uncommitted changes when the
@ -231,127 +232,6 @@ git merge v1.2.3^0
git merge --ff-only v1.2.3
----

HOW CONFLICTS ARE PRESENTED
---------------------------

During a merge, the working tree files are updated to reflect the result
of the merge. Among the changes made to the common ancestor's version,
non-overlapping ones (that is, you changed an area of the file while the
other side left that area intact, or vice versa) are incorporated in the
final result verbatim. When both sides made changes to the same area,
however, Git cannot randomly pick one side over the other, and asks you to
resolve it by leaving what both sides did to that area.

By default, Git uses the same style as the one used by the "merge" program
from the RCS suite to present such a conflicted hunk, like this:

------------
Here are lines that are either unchanged from the common
ancestor, or cleanly resolved because only one side changed,
or cleanly resolved because both sides changed the same way.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
=======
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
And here is another line that is cleanly resolved or unmodified.
------------

The area where a pair of conflicting changes happened is marked with markers
+<<<<<<<+, `=======`, and +>>>>>>>+. The part before the `=======`
is typically your side, and the part afterwards is typically their side.

The default format does not show what the original said in the conflicting
area. You cannot tell how many lines are deleted and replaced with
Barbie's remark on your side. The only thing you can tell is that your
side wants to say it is hard and you'd prefer to go shopping, while the
other side wants to claim it is easy.

An alternative style can be used by setting the `merge.conflictStyle`
configuration variable to either `diff3` or `zdiff3`. In `diff3`
style, the above conflict may look like this:

------------
Here are lines that are either unchanged from the common
ancestor, or cleanly resolved because only one side changed,
<<<<<<< yours:sample.txt
or cleanly resolved because both sides changed the same way.
Conflict resolution is hard;
let's go shopping.
||||||| base:sample.txt
or cleanly resolved because both sides changed identically.
Conflict resolution is hard.
=======
or cleanly resolved because both sides changed the same way.
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
And here is another line that is cleanly resolved or unmodified.
------------

while in `zdiff3` style, it may look like this:

------------
Here are lines that are either unchanged from the common
ancestor, or cleanly resolved because only one side changed,
or cleanly resolved because both sides changed the same way.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
||||||| base:sample.txt
or cleanly resolved because both sides changed identically.
Conflict resolution is hard.
=======
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
And here is another line that is cleanly resolved or unmodified.
------------

In addition to the +<<<<<<<+, `=======`, and +>>>>>>>+ markers, it uses
another +|||||||+ marker that is followed by the original text. You can
tell that the original just stated a fact, and your side simply gave in to
that statement and gave up, while the other side tried to have a more
positive attitude. You can sometimes come up with a better resolution by
viewing the original.


HOW TO RESOLVE CONFLICTS
------------------------

After seeing a conflict, you can do two things:

* Decide not to merge. The only clean-ups you need are to reset
the index file to the `HEAD` commit to reverse 2. and to clean
up working tree changes made by 2. and 3.; `git merge --abort`
can be used for this.

* Resolve the conflicts. Git will mark the conflicts in
the working tree. Edit the files into shape and
`git add` them to the index. Use `git commit` or
`git merge --continue` to seal the deal. The latter command
checks whether there is a (interrupted) merge in progress
before calling `git commit`.

You can work through the conflict with a number of tools:

* Use a mergetool. `git mergetool` to launch a graphical
mergetool which will work through the merge with you.

* Look at the diffs. `git diff` will show a three-way diff,
highlighting changes from both the `HEAD` and `MERGE_HEAD`
versions. `git diff AUTO_MERGE` will show what changes you've
made so far to resolve textual conflicts.

* Look at the diffs from each branch. `git log --merge -p <path>`
will show diffs first for the `HEAD` version and then the
`MERGE_HEAD` version.

* Look at the originals. `git show :1:filename` shows the
common ancestor, `git show :2:filename` shows the `HEAD`
version, and `git show :3:filename` shows the `MERGE_HEAD`
version.


EXAMPLES
--------

@ -406,6 +286,7 @@ linkgit:git-reset[1],
linkgit:git-diff[1], linkgit:git-ls-files[1],
linkgit:git-add[1], linkgit:git-rm[1],
linkgit:git-mergetool[1]
linkgit:gitmergeconflicts[7]

GIT
---

View File

@ -38,7 +38,8 @@ or `pull.ff` with your preferred behaviour.

If there's a merge conflict during the merge or rebase that you don't
want to handle, you can safely abort it with `git merge --abort` or
`git rebase --abort`.
`git rebase --abort`. See linkgit:gitmergeconflicts[7]
(or `git help mergeconflicts`) for a guide to handling merge conflicts.

OPTIONS
-------

View File

@ -46,10 +46,7 @@ If there is a merge conflict during this process, `git rebase` will stop at the
first problematic commit and leave conflict markers. If this happens, you can do
one of these things:

1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
and make edits to resolve the conflict. For each file you edit, you need to
tell Git that the conflict has been resolved. You can mark the conflict as
resolved with `git add <filename>`. After resolving all of the conflicts,
1. Resolve the conflict. After resolving all of the conflicts,
you can continue the rebasing process with

git rebase --continue
@ -62,6 +59,9 @@ one of these things:

git rebase --skip

See linkgit:gitmergeconflicts[7] (or `git help mergeconflicts`)
for a full guide to handling merge conflicts.

If you don't specify an `<upstream>` to rebase onto, the upstream configured in
`branch.<name>.remote` and `branch.<name>.merge` options will be used (see
linkgit:git-config[1] for details) and the `--fork-point` option is
@ -1295,6 +1295,11 @@ include::includes/cmd-config-section-all.adoc[]
include::config/rebase.adoc[]
include::config/sequencer.adoc[]

SEE ALSO
--------

linkgit:gitmergeconflicts[7]

GIT
---
Part of the linkgit:git[1] suite

View File

@ -31,6 +31,10 @@ both will discard uncommitted changes in your working directory.
See "Reset, restore and revert" in linkgit:git[1] for the differences
between the three commands.

Reverting a commit may result in a merge conflict.
See linkgit:gitmergeconflicts[7] (or `git help mergeconflicts`)
for a guide to handling merge conflicts.

OPTIONS
-------
<commit>...::
@ -162,6 +166,7 @@ include::config/revert.adoc[]
SEE ALSO
--------
linkgit:git-cherry-pick[1]
linkgit:gitmergeconflicts[7]

GIT
---

View File

@ -0,0 +1,340 @@
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

View File

@ -204,6 +204,7 @@ manpages = {
'gitfaq.adoc' : 7,
'gitglossary.adoc' : 7,
'gitpacking.adoc' : 7,
'gitmergeconflicts.adoc' : 7,
'gitnamespaces.adoc' : 7,
'gitremote-helpers.adoc' : 7,
'gitrevisions.adoc' : 7,

View File

@ -234,6 +234,7 @@ githooks userinterfaces
gitignore userinterfaces
gitk mainporcelain
gitmailmap userinterfaces
gitmergeconflicts guide
gitmodules userinterfaces
gitnamespaces guide
gitprotocol-capabilities developerinterfaces