Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Documentation/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ MAN7_TXT += gitdiffcore.adoc
MAN7_TXT += giteveryday.adoc

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:

>  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 f8dea4b395..bc49641dda 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

This unfortunately needs to be accompanied with a matching change to
help the other build system.

You probably want to move your change to set conflict-marker-size
for this new file to this step, not at the end as if an
afterthought.


 Documentation/meson.build | 1 +
 1 file changed, 1 insertion(+)

diff --git c/Documentation/meson.build w/Documentation/meson.build
index 51647957e0..10b0637991 100644
--- c/Documentation/meson.build
+++ w/Documentation/meson.build
@@ -201,6 +201,7 @@ manpages = {
   'giteveryday.adoc' : 7,
   'gitfaq.adoc' : 7,
   'gitglossary.adoc' : 7,
+  'gitmergeconflicts.adoc' : 7,
   'gitpacking.adoc' : 7,
   'gitmergeconflicts.adoc' : 7,
   'gitnamespaces.adoc' : 7,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

Junio C Hamano <gitster@pobox.com> writes:

> This unfortunately needs to be accompanied with a matching change to
> help the other build system.

I did get a build failure due to meson, but apparently not due to
this step in the 7-patch series.

> You probably want to move your change to set conflict-marker-size
> for this new file to this step, not at the end as if an
> afterthought.

This still stands, though.

Sorry, a wrong patch and a false alarm.

>
>
>  Documentation/meson.build | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git c/Documentation/meson.build w/Documentation/meson.build
> index 51647957e0..10b0637991 100644
> --- c/Documentation/meson.build
> +++ w/Documentation/meson.build
> @@ -201,6 +201,7 @@ manpages = {
>    'giteveryday.adoc' : 7,
>    'gitfaq.adoc' : 7,
>    'gitglossary.adoc' : 7,
> +  'gitmergeconflicts.adoc' : 7,
>    'gitpacking.adoc' : 7,
>    'gitmergeconflicts.adoc' : 7,
>    'gitnamespaces.adoc' : 7,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Sep 24, 2026 at 02:44:16PM +0000, Julia Evans via GitGitGadget wrote:
> diff --git a/Documentation/gitmergeconflicts.adoc b/Documentation/gitmergeconflicts.adoc
> new file mode 100644
> index 0000000000..612b683e40
> --- /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

Should all of these be using linkgit:, like for example in
linkgit:git-merge[1]?

> +the same merge algorithm, and the process for resolving a merge conflict
> +is always very similar.

There's also git-am(1), but only when adding the "--3way" flag. So maybe
it's best to ignore that command indeed.

> +The most common ways to handle a merge conflict are:
> +
> +* Resolve the conflict. (see <<resolve,HOW TO RESOLVE A MERGE CONFLICT>>
> +  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 <<git_status,EXAMPLE: GIT STATUS OUTPUT>> below
> +  for how to find the command to run.

I wonder whether the explanation should be expanded a bit to briefly
explain how Git performs a 3-way merge in the first place. I feel like
it's quite important to understand what the three different sides of the
merge are to make sense of it.

But I may be too far detached from the "normal" user, so this may only
cause more confusion for our users.

> +[[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

I wonder whether we want to use "hunk" instead of "area". It's jargon
again, but I have never heard anybody speak about an "area" before
myself.

> +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

A bit of a tangent, but sometimes I wonder whether we should make the
respective commits a bit easier to access. For example, we could put the
equivalent of `git rev-parse --reference <commit>` here for each of the
sides.

> +    "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 <<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 the same thing.

s/the the/the/

Maybe we should also say "During a conflicted `git merge`.", but maybe
that's redundant.

> +[[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:

I tend to forget that by default, we only render ours/theirs in the
conflict. I always feel like that makes it way harder to resolve
conflicts as you don't have the context of what the code looked like
originally. So I have diff3 configured locally for ages.

> +----
> +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.

There's also `git merge-tool --tool-help` to list all available drivers.

[snip]
> +[[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.

Indeed.

[snip]
> +[[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.

Hmm. This part is a bit confusing to me. "ours" is always the commit
that's currently checked out, and "theirs" is always the one that is
getting merged into the checked-out commit.

How about a variant of the following instead?

  In a conflict, the side between `<<<<<<<` and `=======` is "ours"
  and the side between `=======` and `>>>>>>>` is "theirs". "Ours" is
  always the side that `HEAD` points to while the merge happens; "theirs"
  is the commit being merged into it.

  For `git merge <other>`, `HEAD` is your current branch, so "ours" is
  your branch and "theirs" is `<other>`.

  For `git rebase <upstream>`, `HEAD` is first moved to `<upstream>` and
  your commits are then replayed on top one at a time. So "ours" is the
  already-rebased history starting at `<upstream>`, and "theirs" is the
  commit from your original branch that is currently being replayed.

> +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"

I wouldn't say that "stage N" is equivalent to the respective other
terms. These stages rather refer to the different versions of a specific
file as recorded in the index, they do not indicate a specific commit.
In contrast to that, all the other terms may also indicate a specific
version of a file, but may also refer to the commits.

Patrick

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Julia Evans" wrote on the Git mailing list (how to reply to this email):

>> +Merge conflicts can happen during a `git merge`, `git rebase`, `git
>> +cherry-pick`, `git pull`, or `git revert`. All of those commands use
>
> Should all of these be using linkgit:, like for example in
> linkgit:git-merge[1]?

Makes sense to me, will change.

>> +The most common ways to handle a merge conflict are:
>> +
>> +* Resolve the conflict. (see <<resolve,HOW TO RESOLVE A MERGE CONFLICT>>
>> +  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 <<git_status,EXAMPLE: GIT STATUS OUTPUT>> below
>> +  for how to find the command to run.
>
> I wonder whether the explanation should be expanded a bit to briefly
> explain how Git performs a 3-way merge in the first place. I feel like
> it's quite important to understand what the three different sides of the
> merge are to make sense of it.
>
> But I may be too far detached from the "normal" user, so this may only
> cause more confusion for our users.

I think it would cause more confusion. I did some experiments in explaining
merge conflicts using the concept of 3-way merge a couple of years
ago and it didn't go well.

My experience was that what users they found the most useful was
learning about the tools Git offers (like `git diff --check` and `diff3`),
so that's why this document focuses on tools and formatting much
more than concepts.

I think it would be cool to find a way to explain how 3-way merge works at in
this document in some later iteration though, maybe at the end. Definitely some
folks would find it interesting. I didn't understand 3-way merge myself until a
couple of years ago and it was fun for me to learn, but it didn't really help me
use Git effectively.

(this is quickly becoming a bit of a novel, but it's often very counterintuitive
how some facts that seem "fundamental" about how Git works actually turn
out to not be very important to understand in practice to use it effectively.
It's something I find tough to talk about on this mailing list because it's something
I've only been able to learn empirically)

>> +[[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
>
> I wonder whether we want to use "hunk" instead of "area". It's jargon
> again, but I have never heard anybody speak about an "area" before
> myself.

Ah thanks, I think I took "area" from the `git-merge` man page.

I looked up how I explained this previously and I used "lines of code",
which I think communicates the same meaning without the jargon.
I'll try that instead.

>> +Note: During a `git merge`, `git commit` and `git merge --continue` do
>> +the the same thing.
>
> s/the the/the/

Will fix. 

>> +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
> Hide quoted text
>
> A bit of a tangent, but sometimes I wonder whether we should make the
> respective commits a bit easier to access. For example, we could put the
> equivalent of `git rev-parse --reference <commit>` here for each of the
> sides.

Personally I'm not sure if the commit ID would do much for me, but I feel
like it would help me if it were possible to include the commit message. 

> I tend to forget that by default, we only render ours/theirs in the
> conflict. I always feel like that makes it way harder to resolve
> conflicts as you don't have the context of what the code looked like
> originally. So I have diff3 configured locally for ages.

Every time I show people diff3 someone tells me how happy they
are to learn it :)

>> +* 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.
>
> There's also `git merge-tool --tool-help` to list all available drivers.

Oh, cool! It's fun that it autodetects which ones you have installed
on your system. I'll suggest that.

>
> [snip]
>> +[[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.
>
> Hmm. This part is a bit confusing to me. "ours" is always the commit
> that's currently checked out, and "theirs" is always the one that is
> getting merged into the checked-out commit.
>
> How about a variant of the following instead?
>
>   In a conflict, the side between `<<<<<<<` and `=======` is "ours"
>   and the side between `=======` and `>>>>>>>` is "theirs". "Ours" is
>   always the side that `HEAD` points to while the merge happens; "theirs"
>   is the commit being merged into it.
>
>   For `git merge <other>`, `HEAD` is your current branch, so "ours" is
>   your branch and "theirs" is `<other>`.
>
>   For `git rebase <upstream>`, `HEAD` is first moved to `<upstream>` and
>   your commits are then replayed on top one at a time. So "ours" is the
>   already-rebased history starting at `<upstream>`, and "theirs" is the
>   commit from your original branch that is currently being replayed.

Thanks, your suggestion gives me some other ways to think about this.

I think I'll try to write something shorter that is unambiguous, instead of trying
to use more words to make it feel more intuitive. I don't think I actually know
anyone who feels it's easy to understand the way merge conflicts are
presented, and more explanation may not help.

It might be more useful here to encourage (again) folks to use one of the many
amazing tools available (in the "tools" section) to get more context.

>> +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"
>
> I wouldn't say that "stage N" is equivalent to the respective other
> terms. These stages rather refer to the different versions of a specific
> file as recorded in the index, they do not indicate a specific commit.
> In contrast to that, all the other terms may also indicate a specific
> version of a file, but may also refer to the commits.

Thanks, will try to figure out how to make it more accurate.
We could also refer to gitdatamodel if folks want to learn what the
term "stage" means too.

Thanks for the review!
- Julia

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans" <julia@jvns.ca> writes:

>>> +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
>> Hide quoted text
>>
>> A bit of a tangent, but sometimes I wonder whether we should make the
>> respective commits a bit easier to access. For example, we could put the
>> equivalent of `git rev-parse --reference <commit>` here for each of the
>> sides.
>
> Personally I'm not sure if the commit ID would do much for me, but I feel
> like it would help me if it were possible to include the commit message. 

It would also help the resolution, not just committing after you are
done.  It may not matter while picking between cherry and banana to
show your personal preference on fruits, but in a more involved
conflicted merge, it may help to be able to view "git show $commit",
"git diff ...$commit", and "git diff $commit..." where $commit is
the "add-fruit" side of the merge to understand what they wanted to
do, and what we have done while they weren't looking.

>> I tend to forget that by default, we only render ours/theirs in the
>> conflict. I always feel like that makes it way harder to resolve
>> conflicts as you don't have the context of what the code looked like
>> originally. So I have diff3 configured locally for ages.
>
> Every time I show people diff3 someone tells me how happy they
> are to learn it :)

Yes, we should encourage "merge.conflictstyle=diff3" (I feel about
this strongly enough to think it should become the default).
Knowing what the original was before one side wanted to say "cherry"
while the other side wanted to say "banana" sometimes helps a great
deal to decide what to do with the conflict.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Wed, Sep 30, 2026 at 01:37:16PM -0700, Junio C Hamano wrote:
> "Julia Evans" <julia@jvns.ca> writes:
> 
> >>> +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
> >> Hide quoted text
> >>
> >> A bit of a tangent, but sometimes I wonder whether we should make the
> >> respective commits a bit easier to access. For example, we could put the
> >> equivalent of `git rev-parse --reference <commit>` here for each of the
> >> sides.
> >
> > Personally I'm not sure if the commit ID would do much for me, but I feel
> > like it would help me if it were possible to include the commit message. 
> 
> It would also help the resolution, not just committing after you are
> done.  It may not matter while picking between cherry and banana to
> show your personal preference on fruits, but in a more involved
> conflicted merge, it may help to be able to view "git show $commit",
> "git diff ...$commit", and "git diff $commit..." where $commit is
> the "add-fruit" side of the merge to understand what they wanted to
> do, and what we have done while they weren't looking.

Yup. Doesn't mean we cannot _also_ include the names that we have above.
So in the above example it could be for example:

+FRUITS = [
+    "apple",
+<<<<<<< HEAD: abcdefg (fruits: add apple, 2026-10-01)
+    "cherry",
+=======
+    "banana",
+>>>>>>> add-fruit: 12345678 (fruits: add banana, 2024-02-03)

That format would have a bunch of advantages:

  - We don't have to teach users about special refs like MERGE_HEAD to
    let them figure out how to access each of the commits.

  - It gives a bit more context about what each specific side does, at
    least if you have good commit messages.

  - It also gives a sense of timing because we include dates, and that
    may help in some situations to figure out what's what.

I'll create an issue on the GitLab side and ask someone in the team to
maybe give this a try.

> >> I tend to forget that by default, we only render ours/theirs in the
> >> conflict. I always feel like that makes it way harder to resolve
> >> conflicts as you don't have the context of what the code looked like
> >> originally. So I have diff3 configured locally for ages.
> >
> > Every time I show people diff3 someone tells me how happy they
> > are to learn it :)
> 
> Yes, we should encourage "merge.conflictstyle=diff3" (I feel about
> this strongly enough to think it should become the default).
> Knowing what the original was before one side wanted to say "cherry"
> while the other side wanted to say "banana" sometimes helps a great
> deal to decide what to do with the conflict.

I very much agree that it should be the default.

Patrick

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Julia Evans" wrote on the Git mailing list (how to reply to this email):

> +FRUITS = [
> +    "apple",
> +<<<<<<< HEAD: abcdefg (fruits: add apple, 2026-10-01)
> +    "cherry",
> +=======
> +    "banana",
> +>>>>>>> add-fruit: 12345678 (fruits: add banana, 2024-02-03)
>
> That format would have a bunch of advantages:
>
>   - We don't have to teach users about special refs like MERGE_HEAD to
>     let them figure out how to access each of the commits.
>
>   - It gives a bit more context about what each specific side does, at
>     least if you have good commit messages.
>
>   - It also gives a sense of timing because we include dates, and that
>     may help in some situations to figure out what's what.

This is so cool, I love the idea of including the dates and the commit
messages!!! I think this would be very helpful for the reasons you say. 

Though re "We don't have to teach users about special refs
like MERGE_HEAD": I think that users today could run`git show HEAD`
or `git show add-fruit` to see the commits on each side? I've never
used MERGE_HEAD though so maybe I'm misunderstanding what
it does. I think adding the commit ID makes it clearer too.

I just ran downstairs to show my partner this example at 8am
because I was so excited about it :) (he liked it too)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

Junio C Hamano <gitster@pobox.com> writes:

>>>> +FRUITS = [
>>>> +    "apple",
>>>> +<<<<<<< HEAD
>>>> +    "cherry",
>>>> +=======
>>>> +    "banana",
>>>> +>>>>>>> add-fruit
>
>> Every time I show people diff3 someone tells me how happy they
>> are to learn it :)
>
> Yes, we should encourage "merge.conflictstyle=diff3" (I feel about
> this strongly enough to think it should become the default).
> Knowing what the original was before one side wanted to say "cherry"
> while the other side wanted to say "banana" sometimes helps a great
> deal to decide what to do with the conflict.

Before I forget, here is a good illustration to tell why diff3 style
is often essential to correct conflict resolution that we can tell
new users.  You may want to throw it in to your new manual pages.

If the conflict looks like this

        FRUITS = [       
            "apple",     
        <<<<<<< HEAD     
            "cherry",    
	|||||||
        =======          
            "banana",    
        >>>>>>> add-fruit

then we can tell that in the beginning there was only 'apple', and
one side wanted to add 'cherry', while the other side wanted to add
'banana'.  It is likely that we would make both sides happy by
adding both of them.

But on the other hand, if the conflict looks like this

        FRUITS = [       
            "apple",     
        <<<<<<< HEAD     
            "cherry",    
	|||||||
	    "banana",
	    "cherry",
        =======          
            "banana",    
        >>>>>>> add-fruit

we can tell that before two sides started editing, we had 'apple',
'banana', and 'cherry'.  While both wanted to keep 'apple', one side
did not want 'banana', and the other side did not want 'cherry'.  It
is plausible that we can please both of them by removing these two.

With just two-sides, the user who is trying to resolve the conflict
cannot tell the difference.

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
Expand Down
23 changes: 4 additions & 19 deletions Documentation/git-cherry-pick.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Julia Evans <julia@jvns.ca>
>
> Remove the discussion of merge conflicts and replace it with a link to
> the guide.
>
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  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 f4cd8b9db7..d93829600b 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.

The new document may explain how to resolve conflicts, but are the
details removed from here that are specific to the 'cherry-pick'
operation also covered there?

For example, during a difficult cherry-pick, it is often handy to be
able to run 'git show CHERRY_PICK_HEAD', but now users are not told
about the pseudo-ref, which seems like a real loss.

The fact that cleanly auto-resolved contents for paths are recorded
in the index may be shared with all other merge-like operations,
and it need not be part of the "how to resolve a conflicted
merge-like operation" recipe, but users need to be assured that this
is what happens somewhere in the documentation set.  The list
removed here served that purpose for this specific command, but it
is now gone.

I do not recall offhand whether we explicitly tell our users that
all merge-like operations update the index with cleanly auto-resolved
results and only leave conflicts to be hand-resolved by the user,
but even if we did so elsewhere, I do not see any reference to that
in the existing text of the 'cherry-pick' manual, nor does this
patch series add such a link.  At least item #2 and #3 should be
kept in the list, I think.  A better alternative might be to add
your new reference, and shorten the description given in item #4,
and leave everything else as before.

Thanks.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Julia Evans" wrote on the Git mailing list (how to reply to this email):

> The new document may explain how to resolve conflicts, but are the
> details removed from here that are specific to the 'cherry-pick'
> operation also covered there?

I'll update this series to make fewer changes to this page as you
suggest to make the diff smaller.

> For example, during a difficult cherry-pick, it is often handy to be
> able to run 'git show CHERRY_PICK_HEAD', but now users are not told
> about the pseudo-ref, which seems like a real loss.

I'll put this back for now, but I removed it because I couldn't
understand why CHERRY_PICK_HEAD might be useful, and some of my user research
showed that almost nobody uses `CHERRY_PICK_HEAD`. I always appreciate people
telling me why these things are actually useful though, and even if very few
people use something, maybe more people would use it if it was clear why it's
useful :)

My best guess (based on what you said) is that `CHERRY_PICK_HEAD` is
only useful if you're cherry-picking multiple commits at the same time.
Is the following an accurate explanation?:

> If the conflict happened when cherry picking multiple commits, you can run
> `git show CHERRY_PICK_HEAD` to see the commit that Git failed to apply.



> The fact that cleanly auto-resolved contents for paths are recorded
> in the index may be shared with all other merge-like operations,
> and it need not be part of the "how to resolve a conflicted
> merge-like operation" recipe, but users need to be assured that this
> is what happens somewhere in the documentation set.  The list
> removed here served that purpose for this specific command, but it
> is now gone.

That makes sense to me. One major benefit of making a
centralized page is that each man page explains different aspects
of the merge conflict process, and we can make sure that anyone
who needs to solve a merge conflict is aware of all the aspects. 
I'll think about how to explain that.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans" <julia@jvns.ca> writes:

> My best guess (based on what you said) is that `CHERRY_PICK_HEAD` is
> only useful if you're cherry-picking multiple commits at the same time.
> Is the following an accurate explanation?:
>
>> If the conflict happened when cherry picking multiple commits, you can run
>> `git show CHERRY_PICK_HEAD` to see the commit that Git failed to apply.

You do not have to limit yourself to the multi-pick case.  If you
make it a habit to use CHERRY_PICK_HEAD, you do not have to remember
exactly which commit you specified on the command line to pick when
stopped by a conflict during a cherry-pick.  This is especially true
for those who have already made it a habit to use MERGE_HEAD when
stopped by a conflict during a merge.  Not having to think when you
can mechanically perform a routine task is bliss.

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
-------
Expand Down Expand Up @@ -259,6 +243,7 @@ $ git cherry-pick -Xpatience topic^ <4>
SEE ALSO
--------
linkgit:git-revert[1]
linkgit:gitmergeconflicts[7]

GIT
---
Expand Down
125 changes: 3 additions & 122 deletions Documentation/git-merge.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"D. Ben Knoble" wrote on the Git mailing list (how to reply to this email):

Hi Julia,

On Thu, Sep 24, 2026 at 10:46 AM Julia Evans via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Julia Evans <julia@jvns.ca>
>
> All of the info about merge conflicts has been moved to the new guide

> 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.

> - * 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.

I think these are both valuable pieces of information we have lost in
the new guide (unless I misremember just having read patch 1 :).

The first explains a bit more about what a conflict *is*. Maybe that's
old-hat nowadays, but I think it could be nice to keep a statement
about why conflicts exist.

The second is a very useful way to get more context to help resolve
conflicts! I have an alias "conflict = log --oneline --graph
--left-right --boundary --merge" for a similar purpose, and I think
the new guide should help folks discover --merge. Often I can get a
better sense of how to resolve conflicts by comparing the original
changes on each side, or I might at least know who to ask about what
to do.

-- 
D. Ben Knoble

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Julia Evans" wrote on the Git mailing list (how to reply to this email):

On Fri, Sep 25, 2026, at 12:36 PM, D. Ben Knoble wrote:
> Hi Julia,
>
> On Thu, Sep 24, 2026 at 10:46 AM Julia Evans via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
>>
>> From: Julia Evans <julia@jvns.ca>
>>
>> All of the info about merge conflicts has been moved to the new guide
>
>> 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.
>
>> - * 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.
>
> I think these are both valuable pieces of information we have lost in
> the new guide (unless I misremember just having read patch 1 :).
>
> The first explains a bit more about what a conflict *is*. Maybe that's
> old-hat nowadays, but I think it could be nice to keep a statement
> about why conflicts exist.

Will think about this!

> The second is a very useful way to get more context to help resolve
> conflicts! I have an alias "conflict = log --oneline --graph
> --left-right --boundary --merge" for a similar purpose, and I think
> the new guide should help folks discover --merge. Often I can get a
> better sense of how to resolve conflicts by comparing the original
> changes on each side, or I might at least know who to ask about what
> to do.

Thanks, I meant to flag this: the reason I deleted it was really
just that I couldn't understand what `git log --merge -p <path>`  did
from the documentation and so I removed it until I could figure it out.
I thought that `--merge` meant that it had something to do with merge
commits, but upon further investigation it looks like that's not true, and
that `--merges` is related to merge commits, `--merge` is something
totally different which is relevant any time there's a conflict

My best guess now is that it would make sense to include this
under "Tools to get more context". Maybe something like this:

> `git log --merge -p <filename>`  will print out all commits which
>   caused the merge conflict for `<filename>`, and the diff
>  of how they changed the file. 

("which caused the merge conflict for" is a little more vague, but
I'm trying to convey the intent, and hopefully folks can look at
`man git log` if they want to know the specifics)

This does sound really useful.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans" <julia@jvns.ca> writes:

> Thanks, I meant to flag this: the reason I deleted it was really
> just that I couldn't understand what `git log --merge -p <path>`  did
> from the documentation and so I removed it until I could figure it out.

It looks at the index to figure out which paths we got conflicts on,
and then does "git log -p <those> <conflicted> <paths>".  You can
give a pathspec from the command line to further limit the output.

>> `git log --merge -p <filename>`  will print out all commits which
>>   caused the merge conflict for `<filename>`, and the diff
>>  of how they changed the file. 

If you _know_ which exact single file you are interested in, there
is not much you gain from the "--merge" option.  "--left-right"
option may be a lot more useful there.  It let's you see which side
of the merge gave you what changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ben Knoble wrote on the Git mailing list (how to reply to this email):

> Le 25 sept. 2026 à 14:19, Junio C Hamano <gitster@pobox.com> a écrit :
> 
> "Julia Evans" <julia@jvns.ca> writes:
> 
>> Thanks, I meant to flag this: the reason I deleted it was really
>> just that I couldn't understand what `git log --merge -p <path>`  did
>> from the documentation and so I removed it until I could figure it out.
> 
> It looks at the index to figure out which paths we got conflicts on,
> and then does "git log -p <those> <conflicted> <paths>".  You can
> give a pathspec from the command line to further limit the output.

This explanation omits the manual’s “HEAD…<other>” argument
that the merge option implies, which is important for
understanding the option and my alias ;)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ben Knoble wrote on the Git mailing list (how to reply to this email):

> Le 25 sept. 2026 à 12:59, Julia Evans <julia@jvns.ca> a écrit :
> 
> 
> 
>> On Fri, Sep 25, 2026, at 12:36 PM, D. Ben Knoble wrote:
>> Hi Julia,

[snip]

>> The second is a very useful way to get more context to help resolve
>> conflicts! I have an alias "conflict = log --oneline --graph
>> --left-right --boundary --merge" for a similar purpose, and I think
>> the new guide should help folks discover --merge. Often I can get a
>> better sense of how to resolve conflicts by comparing the original
>> changes on each side, or I might at least know who to ask about what
>> to do.
> 
> Thanks, I meant to flag this: the reason I deleted it was really
> just that I couldn't understand what `git log --merge -p <path>`  did
> from the documentation and so I removed it until I could figure it out.
> I thought that `--merge` meant that it had something to do with merge
> commits, but upon further investigation it looks like that's not true, and
> that `--merges` is related to merge commits, `--merge` is something
> totally different which is relevant any time there's a conflict
> 
> My best guess now is that it would make sense to include this
> under "Tools to get more context". Maybe something like this:
> 
>> `git log --merge -p <filename>`  will print out all commits which
>>  caused the merge conflict for `<filename>`, and the diff
>> of how they changed the file.
> 
> ("which caused the merge conflict for" is a little more vague, but
> I'm trying to convey the intent, and hopefully folks can look at
> `man git log` if they want to know the specifics)
> 
> This does sound really useful.

That reads well enough for me! Thanks. 

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans" <julia@jvns.ca> writes:

> Like I mentioned before elsewhere it takes a super light approach to
> introducing the 3-way merge. (there is intentionally no mention
> of "since they diverged from the common ancestor" etc)
>
>     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
>     `hello.py`, then it can easily combine them.

Some immediate reactions.

 - Is it obvious that the reason why it can "easily combine" them,
   or would it help to be more explicit (i.e., "as there is no
   overlap")?

 - The second "of `hello.py`" forced me to go back and look at the
   first one again to make sure we are talking about the same file.
   I would imagine if the latter were "lines 20-25 of the same file",
   it would have read better at least to me.

>     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".

 - "cannot guess" would be more direct than "will not try to guess".

>     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

 - "merged without conflicts" would be more direct than "successfully merged".

>     * For the files with conflicts, it leaves them unstaged, puts both
>       sides' edits in the file, and leaves <<markers, merge conflict markers>>
>       that you need to resolve.

 - "unstaged" sounds as if somebody ran "git rm --cached" on the
   paths, but that is not what you want to tell your readers.

 - "it leaves them unstaged" -> "it remembers them as conflicted",
   perhaps?  This hints that Git has a mechanism to remember the
   conflicted paths even after you removed the conflict markers from
   the file to your readers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Julia Evans" wrote on the Git mailing list (how to reply to this email):

>>     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
>>     `hello.py`, then it can easily combine them.
>
> Some immediate reactions.

Thanks, incorporated a few of these ("it marks them as conflicted",
"since there's no overlap", "the same file")

>>     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".
>
>  - "cannot guess" would be more direct than "will not try to guess".

The way I think about it as a user is that Git takes an intentionally conservative
approach and I appreciate the conservatism. Compared to a more aggressive
syntax-aware merge system like `mergiraf` which has done merges I don't
agree with.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Julia Evans" <julia@jvns.ca> writes:

>>  - "cannot guess" would be more direct than "will not try to guess".
>
> The way I think about it as a user is that Git takes an intentionally conservative
> approach and I appreciate the conservatism. Compared to a more aggressive
> syntax-aware merge system like `mergiraf` which has done merges I don't
> agree with.

Your disagreement with their result suggests that they guessed when
they could not do so reliably.  I agree that our approach is more
conservative, but we can call it being more honest.

;-).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"D. Ben Knoble" wrote on the Git mailing list (how to reply to this email):

On Fri, Oct 2, 2026 at 1:01 PM Julia Evans <julia@jvns.ca> wrote:
>
>
>
> On Fri, Sep 25, 2026, at 12:59 PM, Julia Evans wrote:
> > On Fri, Sep 25, 2026, at 12:36 PM, D. Ben Knoble wrote:
> >> Hi Julia,
> >>
> >> On Thu, Sep 24, 2026 at 10:46 AM Julia Evans via GitGitGadget
> >> <gitgitgadget@gmail.com> wrote:
> >>>
> >>> From: Julia Evans <julia@jvns.ca>
> >>>
> >>> All of the info about merge conflicts has been moved to the new guide
> >>
> >>> 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.
>
> >> I think these are both valuable pieces of information we have lost in
> >> the new guide (unless I misremember just having read patch 1 :).
> >>
> >> The first explains a bit more about what a conflict *is*. Maybe that's
> >> old-hat nowadays, but I think it could be nice to keep a statement
> >> about why conflicts exist.
> >
> > Will think about this!
>
> After talking this through with my collaborator Marie, we wrote a new
> "what is a merge conflict?" section which I'll include in the v2.
>
> Like I mentioned before elsewhere it takes a super light approach to
> introducing the 3-way merge. (there is intentionally no mention
> of "since they diverged from the common ancestor" etc)
>
>     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
>     `hello.py`, then it can easily combine them.
>
>     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 leaves them unstaged, puts both
>       sides' edits in the file, and leaves <<markers, merge conflict markers>>
>       that you need to resolve.
>

I quite like this. I'm sure it oversimplifies somewhere, but at least
I personally cannot immediately see where (or how it does any harm to)
;)

Thanks!

PS Unlike Junio---perhaps due to my lack of older Git history and
terminology, despite using Git since 2016?---I would never have read
"unstaged" as *deleted* from the index. Just changed and not updated
in the index (i.e., not "git add"-ed).

-- 
D. Ben Knoble

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"D. Ben Knoble" <ben.knoble@gmail.com> writes:

> PS Unlike Junio---perhaps due to my lack of older Git history and
> terminology, despite using Git since 2016?---I would never have read
> "unstaged" as *deleted* from the index. Just changed and not updated
> in the index (i.e., not "git add"-ed).

I agree such an interpretation is certainly possible.

The verb "to unstage" would be the opposite of "to stage", but it is
ambiguous what kind of oppositeness you want to express.  This is
unlike "to stage" whose possible interpretation is fairly narrow.
You register the contents that you consider desirable for the path
using various means.  On the other hand, "to unstage" is undoing the
result of your earlier act "to stage", but it may mean reverting to
what is recorded in HEAD (i.e., "git reset HEAD -- path"), undoing
the fact that you added a path to the index (i.e., "git rm --cached
-- path").  Neither interpretation is what you want when talking
about what a conflicted merge does to remember the three stages for
a conflicted path in the index.

Hence my suggestion to avoid using the verb.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Sep 24, 2026 at 02:44:17PM +0000, Julia Evans via GitGitGadget wrote:
> From: Julia Evans <julia@jvns.ca>
> 
> All of the info about merge conflicts has been moved to the new guide

Pedantic nit: missing punctuation.

Other than that I agree with Ben, one part that we lose here is some
context on what a merge conflict even is.

Patrick

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
Expand Down Expand Up @@ -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
--------

Expand Down Expand Up @@ -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
---
Expand Down
3 changes: 2 additions & 1 deletion Documentation/git-pull.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------
Expand Down
13 changes: 9 additions & 4 deletions Documentation/git-rebase.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions Documentation/git-revert.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------
<commit>...::
Expand Down Expand Up @@ -162,6 +166,7 @@ include::config/revert.adoc[]
SEE ALSO
--------
linkgit:git-cherry-pick[1]
linkgit:gitmergeconflicts[7]

GIT
---
Expand Down
Loading
Loading