From ad4853dc36cdb883c9a8dc6bda747a5ea318e7a8 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 2 Sep 2026 16:45:55 -0400 Subject: [PATCH 1/7] [doc] Add new gitmergeconflicts man page Introduce a new page, `gitmergeconflicts`, that explains the process of handling a merge conflict in a way that addresses the following issues, which came from feedback from Git users on the current explanation of merge conflicts in the `git merge` man page: - The process for resolving a merge conflict is only explained in the `git merge` man page, even though there are several other commands which can result in conflicts - Sometimes we use "ours" and "theirs" to refer to the two sides of the merge conflicts and sometimes we use HEAD and MERGE_HEAD. It should be consistent. Also the terms "ours" and "theirs" are not explained. Similarly, it says "The part before the `=======` is typically your side...", but doesn't explain what "typically" means. - It introduces the merge format using an analogy to RCS, which very few Git users have ever used - In "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.", it's not clear to users what "2" and "3" are supposed to mean - It uses a cultural reference ("Conflict resolution is hard; let's go shopping.") which is confusing or unfamiliar to some people. I think it would be clearer for users to use a code example instead. - It doesn't explain the difference between diff3 and zdiff3 - It sometimes uses the term "area" and sometimes uses the term "hunk" Also document the unified `--abort`, `--continue` workflow in one place, since it's a really nice example of a place Git has a consistent interface between similar commands. Co-Authored-By: Marie Claire LeBlanc Flanagan Signed-off-by: Julia Evans --- Documentation/Makefile | 1 + Documentation/gitmergeconflicts.adoc | 294 +++++++++++++++++++++++++++ Documentation/meson.build | 1 + 3 files changed, 296 insertions(+) create mode 100644 Documentation/gitmergeconflicts.adoc diff --git a/Documentation/Makefile b/Documentation/Makefile index f8dea4b3953250..bc49641dda70b7 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -58,6 +58,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 diff --git a/Documentation/gitmergeconflicts.adoc b/Documentation/gitmergeconflicts.adoc new file mode 100644 index 00000000000000..612b683e407768 --- /dev/null +++ b/Documentation/gitmergeconflicts.adoc @@ -0,0 +1,294 @@ +gitmergeconflicts(7) +==================== + +NAME +---- +gitmergeconflicts - Guide to handling merge conflicts + + +SYNOPSIS +-------- +Guide to handling merge conflicts + + +DESCRIPTION +----------- + +Merge conflicts can happen during a `git merge`, `git rebase`, `git +cherry-pick`, `git pull`, or `git revert`. All of those commands use +the same merge algorithm, and the process for resolving a merge conflict +is always very similar. + +The most common ways to handle a merge conflict are: + +* Resolve the conflict. (see <> + below for details) +* Or 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 <> below + for how to find the command to run. + + +[[markers]] +MERGE CONFLICT MARKERS +---------------------- + +Merge conflicts happen when both of the sides being merged edit the same +area of a file. When this happens, 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: + +---- +FRUITS = [ + "apple", +<<<<<<< HEAD + "cherry", +======= + "banana", +>>>>>>> add-fruit + "mango", + "orange", +] +---- + +The code from one side of the merge conflict is between `<<<<<<<` and +`=======`, and the code for the other side is between `=======` and +`>>>>>>>`. See <> 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 <> + below for how to find the command to run. ++ +Note: During a `git merge`, `git commit` and `git merge --continue` do +the 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", + "mango", +======= + "banana", + "mango", +>>>>>>> add-fruit + "orange", +] +---- + +Then you might edit that part of the code like this, +which includes 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 option `merge.conflictstyle=diff3`. + See <> below for more. + +* 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. + +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. + +[[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 +* there's one file left with conflicts in it: `fruits.py` + +---- +$ 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 ..." to unstage) + (use "git add ..." to mark resolution) + both modified: fruits.py +---- + + +[[diff3]] +DIFF3 AND ZDIFF3 +---------------- + +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` or `zdiff3`. +This extra context can make it much easier to understand what's +happening in a merge conflict. + +Here's an example of what a merge conflict would look like when using +`diff3`. It shows, in order, the "ours" side of the conflict, the +original code (`"mangoooo"`), and the "theirs" side of the +conflict. With this view, you can see that both sides fixed the spelling +mistake in "mango", and each added one fruit to the list. + +---- +FRUITS = [ + "apple", +<<<<<<< HEAD + "cherry", + "mango", +||||||| 1c22e48 + "mangoooo", +======= + "banana", + "mango", +>>>>>>> add-fruit + "orange", +] +---- + +Here's the same example using `zdiff3`. `zdiff3` takes lines that are +shared between both sides (the `"mango"` line) and moves them outside +the conflicted area. This makes the conflicted area shorter, but the +downside is that it's impossible to tell if `"mango"` was part of the +original list of fruits or not. + +---- +FRUITS = [ + "apple", +<<<<<<< HEAD + "cherry", +||||||| 1c22e48 + "mangoooo", +======= + "banana", +>>>>>>> add-fruit + "mango", + "orange", +] +---- + + +[[ours]] +"OURS" AND "THEIRS" +------------------- + +Git refers to the first part of a merge conflict (between `<<<<<<<` +and `=======`) as "ours" and the second part (between `=======` and +`>>>>>>>`) as "theirs". + +Normally, "ours" is the commit that was checked out before you started +the merge, and "theirs" is the other commit. + +But when the merge conflict was caused by a `git rebase`, it's the +opposite: "theirs" is the commit that was checked out before you started +the merge. This is because under the hood, `git rebase main` checks out +the `main` commit first before doing the merge operation. + +These terms in Git all mean the same thing when dealing with a merge +conflict: + +* "common ancestor", "base", and "stage 1" +* "ours", "us", "stage 2", and `HEAD` +* "theirs", "them", and "stage 3" + +[[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 the way we did in the +<>, 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 diff --git a/Documentation/meson.build b/Documentation/meson.build index f4854f802d455f..51647957e02095 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -202,6 +202,7 @@ manpages = { 'gitfaq.adoc' : 7, 'gitglossary.adoc' : 7, 'gitpacking.adoc' : 7, + 'gitmergeconflicts.adoc' : 7, 'gitnamespaces.adoc' : 7, 'gitremote-helpers.adoc' : 7, 'gitrevisions.adoc' : 7, From a1686a2d82ef9357ecff07c1247092d3dd5ecf95 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Thu, 3 Sep 2026 08:40:35 -0400 Subject: [PATCH 2/7] [doc] git-merge: link to new merge conflicts guide All of the info about merge conflicts has been moved to the new guide Signed-off-by: Julia Evans --- Documentation/git-merge.adoc | 125 +---------------------------------- 1 file changed, 3 insertions(+), 122 deletions(-) diff --git a/Documentation/git-merge.adoc b/Documentation/git-merge.adoc index a055384ad6956c..5b7b41cd10a8be 100644 --- a/Documentation/git-merge.adoc +++ b/Documentation/git-merge.adoc @@ -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 ` - 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 --- From 128d69e482687d05aa854e51843a42c14a315d5b Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Thu, 3 Sep 2026 08:41:01 -0400 Subject: [PATCH 3/7] [doc] git-rebase: link to new merge conflicts guide Remove some of the detail about how to handle a merge conflict, since it's explained in detail in the new guide, and there probably isn't enough detail anyway. Leave the steps since rebase is special and has a `--skip` option which the other commands which cause merge conflicts don't have. Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index f6c22d1598978a..da70aff4983fa9 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -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 `. 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 `` to rebase onto, the upstream configured in `branch..remote` and `branch..merge` options will be used (see linkgit:git-config[1] for details) and the `--fork-point` option is @@ -1284,6 +1284,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 From ab459231e024c5c254ee7f336fcac2e249309bd4 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Thu, 3 Sep 2026 08:49:07 -0400 Subject: [PATCH 4/7] [doc] git-revert: link to new merge conflicts guide Signed-off-by: Julia Evans --- Documentation/git-revert.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/git-revert.adoc b/Documentation/git-revert.adoc index ffba365e63981d..0a84447a4724f0 100644 --- a/Documentation/git-revert.adoc +++ b/Documentation/git-revert.adoc @@ -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. +If there have been new commits since the reverted conflict, there may +be a merge conflict. See linkgit:gitmergeconflicts[7] +(or `git help mergeconflicts`) for a guide to handling merge conflicts. + OPTIONS ------- ...:: @@ -162,6 +166,7 @@ include::config/revert.adoc[] SEE ALSO -------- linkgit:git-cherry-pick[1] +linkgit:gitmergeconflicts[7] GIT --- From 03a6b43b5803e6bd9ebba1a49c34cb42202a7f44 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Thu, 3 Sep 2026 08:49:29 -0400 Subject: [PATCH 5/7] [doc] git-cherry-pick: link to new merge conflicts guide Remove the discussion of merge conflicts and replace it with a link to the guide. Signed-off-by: Julia Evans --- Documentation/git-cherry-pick.adoc | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/Documentation/git-cherry-pick.adoc b/Documentation/git-cherry-pick.adoc index f4cd8b9db7a954..d93829600b8fc5 100644 --- a/Documentation/git-cherry-pick.adoc +++ b/Documentation/git-cherry-pick.adoc @@ -19,25 +19,9 @@ 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: - -1. The current branch and `HEAD` pointer stay at the last commit - successfully made. -2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that - introduced the change that is difficult to apply, unless the - `--no-commit` option was given. -3. Paths in which the change applied cleanly are updated both - in the index file and in your working tree. -4. For conflicting paths, the index file records up to three - versions, as described in the "TRUE MERGE" section of - linkgit:git-merge[1]. The working tree files will include - a description of the conflict bracketed by the usual - conflict markers `<<<<<<<` and `>>>>>>>`. -5. No other modifications are made. - -See linkgit:git-merge[1] for some hints on resolving such -conflicts. +When it is not obvious how to apply a change, there may +be a merge conflict. See linkgit:gitmergeconflicts[7] +(or `git help mergeconflicts`) for a guide to handling merge conflicts. OPTIONS ------- @@ -259,6 +243,7 @@ $ git cherry-pick -Xpatience topic^ <4> SEE ALSO -------- linkgit:git-revert[1] +linkgit:gitmergeconflicts[7] GIT --- From d3904f0ca7ad0c2274d642dfc72b863647df487f Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Thu, 3 Sep 2026 09:32:47 -0400 Subject: [PATCH 6/7] [doc] git-pull: link to new merge conflicts guide Signed-off-by: Julia Evans --- Documentation/git-pull.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/git-pull.adoc b/Documentation/git-pull.adoc index 88f4fd3926981e..73f6d460bbb51c 100644 --- a/Documentation/git-pull.adoc +++ b/Documentation/git-pull.adoc @@ -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 ------- From 4505fdc9a6dec37296952107c90947e43f39bae4 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 23 Sep 2026 11:51:38 -0400 Subject: [PATCH 7/7] [doc] ignore conflict markers in gitmergeconflicts.adoc Signed-off-by: Julia Evans --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 26490ad60a74d0..0a0fc950b169ec 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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