threads / patch / 22353

v2, 7 partsclarify 'git merge' documentation

Subject: [PATCH v2 0/7] clarify 'git merge' documentation

## tl;dr

11 messages between Jan 23, 2010 and Feb 12, 2010. Diffs are folded; open one to read it.

replies: 10people: 4as markdown or json

Jonathan Nieder· Jan 23, 2010, 09:25 UTC · lore

For the previous round [1], I wrote something like this to clarify why merging with dirty trees is safe. I hope it also makes git-merge.1 more useful for other purposes. I have not changed the warning in question, which belongs to a different topic.

Patches 1-3 move some material towards the end of the 'merge' manual, to make the manpage easier to read straight through.

Patch 4 adds a brief introduction for the reader who might not yet be familiar with branching and merging. I am especially interested in feedback on this one. My writing tends not to be as clear as I would like. Already some advice from Junio helped a great deal.

Patches 5-7 organize the material on how the merge works into short, digestible pieces. Patch 5 explains how a merge can abort without doing anything, patch 6 the fast-forward merge, and patch 7 the true merge, all from the point of view of what matters for the person invoking ‘git merge’. Patch 7 is basically rewritten using Thomas’s advice.

The patches are against doc-style/for-next of Thomas’s repo at git://repo.or.cz/git/trast .

The advice from last round was very helpful. Apologies for taking so long to respond to it.

Enjoy,
Jonathan Nieder (7):
  Documentation: merge: move configuration section to end
  Documentation: suggest `reset --merge` in How Merge Works section
  Documentation: merge: move merge strategy list to end
  Documentation: merge: add an overview
  Documentation: emphasize when git merge terminates early
  Documentation: merge: add a section about fast-forward
  Documentation: simplify How Merge Works
 Documentation/git-merge.txt |  164 ++++++++++++++++++++++++-------------------
 1 files changed, 92 insertions(+), 72 deletions(-)
[1] http://thread.gmane.org/gmane.comp.version-control.git/136356/focus=136617
Jonathan Nieder· Jan 23, 2010, 09:26 UTC · re: Jonathan Nieder · lore

[PATCH 1/7] Documentation: merge: move configuration section to end

Configuration and environment variables belong to the back matter of a manual page.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Acked-by: Petr Baudis <pasky@suse.cz>
---
 Documentation/git-merge.txt |   18 +++++++++---------
 1 files changed, 9 insertions(+), 9 deletions(-)
Show changes to Documentation/git-merge.txt +9 −8
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index c88bebe..6aa2bf3 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -48,15 +48,6 @@ include::merge-strategies.txt[]
 If you tried a merge which resulted in complex conflicts and
 want to start over, you can recover with 'git reset'.
 
-CONFIGURATION
--------------
-include::merge-config.txt[]
-
-branch.<name>.mergeoptions::
-	Sets default options for merging into branch <name>. The syntax and
-	supported options are the same as those of 'git merge', but option
-	values containing whitespace characters are currently not supported.
-
 HOW MERGE WORKS
 ---------------
 
@@ -249,6 +240,15 @@ changes into a merge commit.  Small fixups like bumping
 release/version name would be acceptable.
 
 
+CONFIGURATION
+-------------
+include::merge-config.txt[]
+
+branch.<name>.mergeoptions::
+	Sets default options for merging into branch <name>. The syntax and
+	supported options are the same as those of 'git merge', but option
+	values containing whitespace characters are currently not supported.
+
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
-- 
1.6.6
Jonathan Nieder· Jan 23, 2010, 09:31 UTC · re: Jonathan Nieder · lore

[PATCH 2/7] Documentation: suggest `reset --merge` in How Merge Works section

The 'merge' manual suggests 'reset' to cancel a merge at the end of the Merge Strategies list. It is more logical to explain this right before explaining how merge conflicts work, so the daunted reader can have a way out when he or she needs it most.

While at it, make the advice more dependable and self-contained by providing the --merge option.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
This should make the reference to 'git reset' easier to find on
second reading.  Something like this ought to happen if we are
going to move the Merge Strategies list down towards the end of
the man page.
 Documentation/git-merge.txt |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
Show changes to Documentation/git-merge.txt +3 −3
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 6aa2bf3..1fecedb 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -45,9 +45,6 @@ include::merge-options.txt[]
 include::merge-strategies.txt[]
 
 
-If you tried a merge which resulted in complex conflicts and
-want to start over, you can recover with 'git reset'.
-
 HOW MERGE WORKS
 ---------------
 
@@ -115,6 +112,9 @@ When there are conflicts, the following happens:
    same and the index entries for them stay as they were,
    i.e. matching `HEAD`.
 
+If you tried a merge which resulted in complex conflicts and
+want to start over, you can recover with `git reset --merge`.
+
 HOW CONFLICTS ARE PRESENTED
 ---------------------------
 
-- 
1.6.6
Jonathan Nieder· Jan 23, 2010, 09:33 UTC · re: Jonathan Nieder · lore

[PATCH 3/7] Documentation: merge: move merge strategy list to end

So the section layout changes as follows:
 NAME
 SYNOPSIS
 DESCRIPTION
 OPTIONS
-MERGE STRATEGIES
 HOW MERGE WORKS
 HOW CONFLICTS ARE PRESENTED
 HOW TO RESOLVE CONFLICTS
 EXAMPLES
+MERGE STRATEGIES
 CONFIGURATION
 SEE ALSO
 AUTHOR
 DOCUMENTATION
 GIT
 NOTES

The first-time user will care more about conflicts than about strategies other than 'recursive'.

One of the examples uses -s ours, but I do not think this hinders readability.

Suggested-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Thomas Rast wrote [1]:
Show 5 quoted lines
> While I agree with the general intent of deferring the strategies
> further back, wouldn't it be better go all the way and instead put
> them before (or even after, but one of them uses -s ours) "EXAMPLES"?
> The average user will care more about conflicts than about strategies
> other than 'recursive'.
Good idea.  Thanks!
[1] http://thread.gmane.org/gmane.comp.version-control.git/136356/focus=136679
 Documentation/git-merge.txt |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
Show changes to Documentation/git-merge.txt +2 −2
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 1fecedb..83bf3e7 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -42,8 +42,6 @@ include::merge-options.txt[]
 	You need at least one <commit>.  Specifying more than one
 	<commit> obviously means you are trying an Octopus.
 
-include::merge-strategies.txt[]
-
 
 HOW MERGE WORKS
 ---------------
@@ -240,6 +238,8 @@ changes into a merge commit.  Small fixups like bumping
 release/version name would be acceptable.
 
 
+include::merge-strategies.txt[]
+
 CONFIGURATION
 -------------
 include::merge-config.txt[]
-- 
1.6.6
Jonathan Nieder· Jan 23, 2010, 09:42 UTC · re: Jonathan Nieder · lore

[PATCH 4/7] Documentation: merge: add an overview

The reader unfamiliar with the concepts of branching and merging would have been completely lost. Try to help him with a diagram.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
The advice in [1] was very helpful.  I fear I’ve made a mess of
the language even so.  At least it does seem much clearer now.
Thoughts?
[1] http://thread.gmane.org/gmane.comp.version-control.git/136356/focus=136629
 Documentation/git-merge.txt |   28 ++++++++++++++++++++++++++--
 1 files changed, 26 insertions(+), 2 deletions(-)
Show changes to Documentation/git-merge.txt +26 −2
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 83bf3e7..a7a40c6 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -15,8 +15,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Merges the history specified by <commit> into HEAD, optionally using a
-specific merge strategy.
+Incorporates changes from the named commits (since the time their
+histories diverged from the current branch) into the current
+branch.  This command is used by 'git pull' to incorporate changes
+from another repository and can be used by hand to merge changes
+from one branch into another.
+
+Assume the following history exists and the current branch is
+"`master`":
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+Then "`git merge topic`" will replay the changes made on the
+`topic` branch since it diverged from `master` (i.e., `E`) until
+its current commit (`C`) on top of `master`, and record the result
+in a new commit along with the names of the two parent commits and
+a log message from the user describing the changes.
+
+------------
+          A---B---C topic
+         /         \
+    D---E---F---G---H master
+------------
 
 The second syntax (<msg> `HEAD` <commit>...) is supported for
 historical reasons.  Do not use it from the command line or in
-- 
1.6.6
Raja R Harinath· Feb 12, 2010, 14:15 UTC · re: Jonathan Nieder · lore

Re: [PATCH 4/7] Documentation: merge: add an overview

Hi,

Jonathan Nieder <jrnieder@gmail.com> writes: [snip]

Show 14 quoted lines
> +Assume the following history exists and the current branch is
> +"`master`":
> +
> +------------
> +          A---B---C topic
> +         /
> +    D---E---F---G master
> +------------
> +
> +Then "`git merge topic`" will replay the changes made on the
> +`topic` branch since it diverged from `master` (i.e., `E`) until
> +its current commit (`C`) on top of `master`, and record the result
> +in a new commit along with the names of the two parent commits and
> +a log message from the user describing the changes.

The word 'replay' seems inappropriate for a description of 'merge'. To me 'replay' seems a synonym of 'rebase' (and IIRC tla has a 'replay' command that was similar to 'rebase' [1]).

(Yeah, I know, I'm responding 3 weeks too late, and the patch is already in the tree.)

- Hari
[1] http://www.gnu.org/software/gnu-arch/tutorial/Introducing-replay-_002d_002d-An-Alternative-to-update.html
Jonathan Nieder· Jan 23, 2010, 09:44 UTC · re: Jonathan Nieder · lore

[PATCH 5/7] Documentation: emphasize when git merge terminates early

A merge-based operation in git can fail in two ways: one that stops before touching anything, or one that goes ahead and results in conflicts.

As the 'git merge' manual explains:
| A merge is always between the current `HEAD` and one or more
| commits (usually, branch head or tag), and the index file must
| match the tree of `HEAD` commit (i.e. the contents of the last commit)
| when it starts out.

Unfortunately, the placement of this sentence makes it easy to skip over, and its formulation leaves the important point, that any other attempted merge will be gracefully aborted, unspoken.

So give this point its own section and expand upon it.

Probably this could be simplified somewhat: after all, a change registered in the index is just a special kind of local uncommited change, so the second added paragraph is only a special case of the first. It seemed more helpful to be explicit here.

Inspired by <http://gitster.livejournal.com/25801.html>.
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Too technical?
 Documentation/git-merge.txt |   31 +++++++++++++++++++++----------
 1 files changed, 21 insertions(+), 10 deletions(-)
Show changes to Documentation/git-merge.txt +21 −10
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index a7a40c6..3663d58 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -67,21 +67,32 @@ include::merge-options.txt[]
 	<commit> obviously means you are trying an Octopus.
 
 
+PRE-MERGE CHECKS
+----------------
+
+Before applying outside changes, you should get your own work in
+good shape and committed locally, so it will not be clobbered if
+there are conflicts.  See also linkgit:git-stash[1].
+'git pull' and 'git merge' will stop without doing anything when
+local uncommitted changes overlap with files that 'git pull'/'git
+merge' may need to update.
+
+To avoid recording unrelated changes in the merge commit,
+'git pull' and 'git merge' will also abort if there are any changes
+registered in the index relative to the `HEAD` commit.  (One
+exception is when the changed index entries are in the state that
+would result from the merge already.)
+
+If all named commits are already ancestors of `HEAD`, 'git merge'
+will exit early with the message "Already up-to-date."
+
 HOW MERGE WORKS
 ---------------
 
 A merge is always between the current `HEAD` and one or more
-commits (usually, branch head or tag), and the index file must
-match the tree of `HEAD` commit (i.e. the contents of the last commit)
-when it starts out.  In other words, `git diff --cached HEAD` must
-report no changes.  (One exception is when the changed index
-entries are already in the same state that would result from
-the merge anyway.)
-
-Three kinds of merge can happen:
+commits (usually a branch head or tag).
 
-* The merged commit is already contained in `HEAD`. This is the
-  simplest case, called "Already up-to-date."
+Two kinds of merge can happen:
 
 * `HEAD` is already contained in the merged commit. This is the
   most common case especially when invoked from 'git pull':
-- 
1.6.6
Jonathan Nieder· Jan 23, 2010, 09:45 UTC · re: Jonathan Nieder · lore

[PATCH 6/7] Documentation: merge: add a section about fast-forward

Novices sometimes find the behavior of 'git merge' in the fast-forward case surprising. Describe it thoroughly.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Sometimes people ask on IRC.
 Documentation/git-merge.txt |   31 ++++++++++++++++++-------------
 1 files changed, 18 insertions(+), 13 deletions(-)
Show changes to Documentation/git-merge.txt +18 −13
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 3663d58..0b86f2b 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -86,25 +86,30 @@ would result from the merge already.)
 If all named commits are already ancestors of `HEAD`, 'git merge'
 will exit early with the message "Already up-to-date."
 
+FAST-FORWARD MERGE
+------------------
+
+Often the current branch head is an ancestor of the named commit.
+This is the most common case especially when invoked from 'git
+pull': you are tracking an upstream repository, you have committed
+no local changes, and now you want to update to a newer upstream
+revision.  In this case, a new commit is not needed to store the
+combined history; instead, the `HEAD` (along with the index) is
+updated to point at the named commit, without creating an extra
+merge commit.
+
+This behavior can be suppressed with the `--no-ff` option.
+
 HOW MERGE WORKS
 ---------------
 
 A merge is always between the current `HEAD` and one or more
 commits (usually a branch head or tag).
 
-Two kinds of merge can happen:
-
-* `HEAD` is already contained in the merged commit. This is the
-  most common case especially when invoked from 'git pull':
-  you are tracking an upstream repository, have committed no local
-  changes and now you want to update to a newer upstream revision.
-  Your `HEAD` (and the index) is updated to point at the merged
-  commit, without creating an extra merge commit.  This is
-  called "Fast-forward".
-
-* Both the merged commit and `HEAD` are independent and must be
-  tied together by a merge commit that has both of them as its parents.
-  The rest of this section describes this "True merge" case.
+Except in a fast-forward merge (see above), the branches to be
+merged must be tied together by a merge commit that has both of them
+as its parents.
+The rest of this section describes this "True merge" case.
 
 The chosen merge strategy merges the two commits into a single
 new source tree.
-- 
1.6.6
Jonathan Nieder· Jan 23, 2010, 09:48 UTC · re: Jonathan Nieder · lore

[PATCH 7/7] Documentation: simplify How Merge Works

The user most likely does not care about the exact order of operations because he cannot see it happening anyway. Instead, try to explain what it means to merge two commits into a single tree.

While at it:
 - Change the heading to TRUE MERGE.  The entire manual page is
   about how merges work.
 - Document MERGE_HEAD.  It is a useful feature, since it makes
   the parents of the intended merge commit easier to refer to.
 - Do not assume commits named on the 'git merge' command line come
   from another repository.  For simplicity, the discussion of
   conflicts still does assume that there is only one and it is a
   branch head.
 - Do not start list items with `code`.  Otherwise, a toolchain bug
   produces a line break in the generated nroff, resulting in odd
   extra space.
Suggested-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
This is the end of series.  Thanks for reading.
Thomas Rast wrote: [1]
> So how about
[...]
> and then snip everything up to
Oh!  Much better, thanks.
[1] http://thread.gmane.org/gmane.comp.version-control.git/136356/focus=136629
 Documentation/git-merge.txt |   52 +++++++++++++-----------------------------
 1 files changed, 16 insertions(+), 36 deletions(-)
Show changes to Documentation/git-merge.txt +16 −35
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 0b86f2b..7aa3f3f 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -100,52 +100,32 @@ merge commit.
 
 This behavior can be suppressed with the `--no-ff` option.
 
-HOW MERGE WORKS
----------------
-
-A merge is always between the current `HEAD` and one or more
-commits (usually a branch head or tag).
+TRUE MERGE
+----------
 
 Except in a fast-forward merge (see above), the branches to be
 merged must be tied together by a merge commit that has both of them
 as its parents.
-The rest of this section describes this "True merge" case.
-
-The chosen merge strategy merges the two commits into a single
-new source tree.
-When things merge cleanly, this is what happens:
-
-1. The results are updated both in the index file and in your
-   working tree;
-2. Index file is written out as a tree;
-3. The tree gets committed; and
-4. The `HEAD` pointer gets advanced.
 
-Because of 2., we require that the original state of the index
-file matches exactly the current `HEAD` commit; otherwise we
-will write out your local changes already registered in your
-index file along with the merge result, which is not good.
-Because 1. involves only those paths differing between your
-branch and the branch you are merging
-(which is typically a fraction of the whole tree), you can
-have local modifications in your working tree as long as they do
-not overlap with what the merge updates.
+A merged version reconciling the changes from all branches to be
+merged is committed, and your `HEAD`, index, and working tree are
+updated to it.  It is possible to have modifications in the working
+tree as long as they do not overlap; the update will preserve them.
 
-When there are conflicts, the following happens:
+When it is not obvious how to reconcile the changes, the following
+happens:
 
-1. `HEAD` stays the same.
-
-2. Cleanly merged paths are updated both in the index file and
+1. The `HEAD` pointer stays the same.
+2. The `MERGE_HEAD` ref is set to point to the other branch head.
+3. Paths that merged cleanly are updated both in the index file and
    in your working tree.
-
-3. For conflicting paths, the index file records up to three
-   versions; stage1 stores the version from the common ancestor,
-   stage2 from `HEAD`, and stage3 from the other branch (you
+4. For conflicting paths, the index file records up to three
+   versions: stage 1 stores the version from the common ancestor,
+   stage 2 from `HEAD`, and stage 3 from `MERGE_HEAD` (you
    can inspect the stages with `git ls-files -u`).  The working
    tree files contain the result of the "merge" program; i.e. 3-way
-   merge results with familiar conflict markers `<<< === >>>`.
-
-4. No other changes are done.  In particular, the local
+   merge results with familiar conflict markers `<<<` `===` `>>>`.
+5. No other changes are made.  In particular, the local
    modifications you had before you started merge will stay the
    same and the index entries for them stay as they were,
    i.e. matching `HEAD`.
-- 
1.6.6
Thomas Rast· Jan 24, 2010, 13:25 UTC · re: Jonathan Nieder · lore

Re: [PATCH v2 0/7] clarify 'git merge' documentation

On Saturday 23 January 2010 10:25:51 Jonathan Nieder wrote:
Show 8 quoted lines
> Jonathan Nieder (7):
>   Documentation: merge: move configuration section to end
>   Documentation: suggest `reset --merge` in How Merge Works section
>   Documentation: merge: move merge strategy list to end
>   Documentation: merge: add an overview
>   Documentation: emphasize when git merge terminates early
>   Documentation: merge: add a section about fast-forward
>   Documentation: simplify How Merge Works
[and in the other thread]
> Jonathan Nieder (1):
>   Documentation: merge: use MERGE_HEAD to refer to the remote branch
Thanks Jonathan!  Ack on all of them.
I still had the following patches in my little documentation queue:
  Jonathan Nieder (2):
    Documentation: git gc packs refs by default now
    Documentation: tiny git config manual tweaks
  Thomas Rast (2):
    Documentation: show-files is now called git-ls-files
    Documentation: emphasise 'git shortlog' in its synopsis

I actually forgot to post the last one, which I'll do shortly, but it's trivial so I just included it at the bottom.

Junio, I gathered all of the above patches and pushed them again to
  git://repo.or.cz/git/trast.git doc-style/for-next

If that's ok and you merge it, I'll declare this the end of this little topic. Admittedly it grew a bit outside the original area of style fixes into a half-rewrite of git-merge(1).

-- 8< --
Subject: [PATCH] Documentation: emphasise 'git shortlog' in its synopsis

The accepted style in the SYNOPSIS section is for a command to be 'emphasised'. Do so for the git-shortlog(1) manpage.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Show changes to Documentation/git-shortlog.txt +1 −1
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index ecf9e27..dfd4d0c 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 git log --pretty=short | 'git shortlog' [-h] [-n] [-s] [-e] [-w]
-git shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
+'git shortlog' [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
 
 DESCRIPTION
 -----------
-- 
Thomas Rast
trast@{inf,student}.ethz.ch

← back to recent threads