[PATCH] Documentation/git-merge.txt: Expand the How Merge Works section

Subsystems: documentation, the rest

DORMANTno replies

4 messages, 2 authors, 2016-06-15 · open the first message on its own page

[PATCH] Documentation/git-merge.txt: Expand the How Merge Works section

From: Petr Baudis <hidden>
Date: 2016-06-15 22:44:57

The git-merge documentation's "HOW MERGE WORKS" section is confusingly
composed and actually omits the most interesting part, the merging of
the arguments into HEAD itself, surprisingly not actually mentioning
the fast-forward merge anywhere.

This patch moves the "[NOTE]" screenful of highly technical details
to a dedicated subsection at the end of the section, and instead
explains how are the arguments compard with HEAD and the three possible
inclusion states. When discussing merges, some term that describes the
situation when fast-forwarding did _not_ happen is frequently useful;
this patch proposes "true merge" for that. It also makes it clear that
the rest of the section talks only about the true merge situation.

Signed-off-by: Petr Baudis <redacted>
---

 Documentation/git-merge.txt |   93 +++++++++++++++++++++++++++----------------
 foo                         |    1 
 2 files changed, 59 insertions(+), 35 deletions(-)
 create mode 100644 foo
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 019e4ca..396f3ec 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -61,46 +61,28 @@ exactly match the
 tree of `HEAD` commit (i.e. the contents of the last commit) when
 it happens.  In other words, `git diff --cached HEAD` must
 report no changes.
+(However, see the "Pre-flight requirements" subsection.)
 
-[NOTE]
-This is a bit of a lie.  In certain special cases, your index is
-allowed to be different from the tree of the `HEAD` commit.  The most
-notable case is when your `HEAD` commit is already ahead of what
-is being merged, in which case your index can have arbitrary
-differences from your `HEAD` commit.  Also, your index entries
-may have differences from your `HEAD` commit that match
-the result of a trivial merge (e.g. you received the same patch
-from an external source to produce the same result as what you are
-merging).  For example, if a path did not exist in the common
-ancestor and your head commit but exists in the tree you are
-merging into your repository, and if you already happen to have
-that path exactly in your index, the merge does not have to
-fail.
+Three kinds of merge can happen:
 
-Otherwise, merge will refuse to do any harm to your repository
-(that is, it may fetch the objects from remote, and it may even
-update the local branch used to keep track of the remote branch
-with `git pull remote rbranch:lbranch`, but your working tree,
-`.git/HEAD` pointer and index file are left intact).  In addition,
-merge always sets `.git/ORIG_HEAD` to the original state of HEAD so
-a problematic merge can be removed by using `git reset ORIG_HEAD`.
+* The merged commit is already contained in `HEAD`. This is the
+  simplest case and only "Already up-to-date" is printed.
 
-You may have local modifications in the working tree files.  In
-other words, 'git-diff' is allowed to report changes.
-However, the merge uses your working tree as the working area,
-and in order to prevent the merge operation from losing such
-changes, it makes sure that they do not interfere with the
-merge. Those complex tables in read-tree documentation define
-what it means for a path to "interfere with the merge".  And if
-your local modifications interfere with the merge, again, it
-stops before touching anything.
+* `HEAD` is already contained in the merged commit. This is the
+  most common case especially when involved through 'git pull':
+  you are tracking an upstream repository, committed no local
+  changes and now you want to update to a newer upstream revision.
+  So-called "fast-forward merge" is performed, simply repointing
+  your `HEAD` (and index) to the merged commit; no extra merge
+  commit is created.
 
-So in the above two "failed merge" case, you do not have to
-worry about loss of data --- you simply were not ready to do
-a merge, so no merge happened at all.  You may want to finish
-whatever you were in the middle of doing, and retry the same
-pull after you are done and ready.
+* Both merged commit and `HEAD` are independent and must be
+  "tied together" by a merge commit, having them both as its parents;
+  this might be called a "true merge" and is described in the rest
+  of this section.
 
+The chosen merge strategy merges the two commits into a single
+new source tree.
 When things cleanly merge, these things happen:
 
 1. The results are updated both in the index file and in your
@@ -152,6 +134,47 @@ After seeing a conflict, you can do two things:
    should be, and run 'git-commit' to commit the result.
 
 
+Pre-flight requirements note
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In certain special cases, your index is
+allowed to be different from the tree of the `HEAD` commit.  The most
+notable case is when your `HEAD` commit is already ahead of what
+is being merged, in which case your index can have arbitrary
+differences from your `HEAD` commit.  Also, your index entries
+may have differences from your `HEAD` commit that match
+the result of a trivial merge (e.g. you received the same patch
+from an external source to produce the same result as what you are
+merging).  For example, if a path did not exist in the common
+ancestor and your head commit but exists in the tree you are
+merging into your repository, and if you already happen to have
+that path exactly in your index, the merge does not have to
+fail.
+
+Other than that, merge will refuse to do any harm to your repository
+(that is, it may fetch the objects from remote, and it may even
+update the local branch used to keep track of the remote branch
+with `git pull remote rbranch:lbranch`, but your working tree,
+`.git/HEAD` pointer and index file are left intact).  In addition,
+merge always sets `.git/ORIG_HEAD` to the original state of HEAD so
+a problematic merge can be removed by using `git reset ORIG_HEAD`.
+
+You may have local modifications in the working tree files.  In
+other words, 'git-diff' is allowed to report changes.
+However, the merge uses your working tree as the working area,
+and in order to prevent the merge operation from losing such
+changes, it makes sure that they do not interfere with the
+merge. Those complex tables in read-tree documentation define
+what it means for a path to "interfere with the merge".  And if
+your local modifications interfere with the merge, again, it
+stops before touching anything.
+
+So in the above two "failed merge" case, you do not have to
+worry about loss of data --- you simply were not ready to do
+a merge, so no merge happened at all.  You may want to finish
+whatever you were in the middle of doing, and retry the same
+pull after you are done and ready.
+
+
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
diff --git a/foo b/foo
new file mode 100644
index 0000000..b4e94ec
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+Thu Jul 17 17:30:53 CEST 2008

Re: [PATCH] Documentation/git-merge.txt: Expand the How Merge Works section

From: Petr Baudis <hidden>
Date: 2016-06-15 22:44:57

On Thu, Jul 17, 2008 at 06:29:32PM +0200, Petr Baudis wrote:
 foo                         |    1 
 2 files changed, 59 insertions(+), 35 deletions(-)
 create mode 100644 foo
*Cough* Sorry about this. I think there is currently no need to merge
the 'foo' bit. ;-)

				Petr "Pasky" Baudis

Re: [PATCH] Documentation/git-merge.txt: Expand the How Merge Works section

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:44:57

Petr Baudis [off-list ref] writes:
The git-merge documentation's "HOW MERGE WORKS" section is confusingly
composed and actually omits the most interesting part, the merging of
the arguments into HEAD itself, surprisingly not actually mentioning
the fast-forward merge anywhere.
Thanks.
+Three kinds of merge can happen:
 
+* The merged commit is already contained in `HEAD`. This is the
+  simplest case and only "Already up-to-date" is printed.
Let's introduce and define terms here, because I think the readers will be
harmed by being given a weak "this _might_ be called" in later paragraph.

I.e.:

	... This is the simplest case and called "Already up-to-date".
+* `HEAD` is already contained in the merged commit. This is the
+  most common case especially when involved through 'git pull':
+  you are tracking an upstream repository, committed no local
+  changes and now you want to update to a newer upstream revision.
+  So-called "fast-forward merge" is performed, simply repointing
+  your `HEAD` (and index) to the merged commit; no extra merge
+  commit is created.
I'd suggest rewording the last three lines:

	Your `HEAD` (and the index) is updated to point the merged
        commit, without creating an extra merge commit.  This is
        called "Fast-forward".
+* Both merged commit and `HEAD` are independent and must be
+  "tied together" by a merge commit, having them both as its parents;
+  this might be called a "true merge" and is described in the rest
+  of this section.
And this becomes:

	... both as its parents.  The rest of this section describes this
	"True merge" case.
+Pre-flight requirements note
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In certain special cases, your index is
+allowed to be different from the tree of the `HEAD` commit.
Now this paragraph is moved far away from the original context that said
"your index must be clean before you start your merge", you would need to
re-introduce that in this sentenece:

	... tree of the `HEAD` before you run 'git-merge'.
+...  The most
+notable case is when your `HEAD` commit is already ahead of what
+is being merged, in which case your index can have arbitrary
+differences from your `HEAD` commit.
Thanks to your re-organization, we now have established terminology when
the reader reads this part, so we can just say:

	When the merge will be "Already-up-to-date", your index can have
	...
+... Also, your index entries
+may have differences from your `HEAD` commit that match
+the result of a trivial merge (e.g. you received the same patch
+from an external source to produce the same result as what you are
+merging).  For example, if a path did not exist in the common
+ancestor and your head commit but exists in the tree you are
+merging into your repository, and if you already happen to have
+that path exactly in your index, the merge does not have to
+fail.
I originally wrote the above paragraph purely for completeness, but I
wonder if this happens a lot in practice.  This is not something the user
can easily anticipate anyway, so we might want to drop this.
+Other than that, merge will refuse to do any harm to your repository
My initial reaction to this "Other than that" was "Huh?  so the special
case we just saw allows merge to do harm to my repository?".  The original
"Otherwise" wasn't any better, either.

	In all other cases, your index must match the `HEAD` commit, even
	though you can have local changes in your working tree, as
	described below.  Merge will avoid doing any harm to your working
	tree state and your repository by refusing to work if such local
	changes conflict with the merged result, though.


+So in the above two "failed merge" case, you do not have to
+worry about loss of data --- you simply were not ready to do
+a merge, so no merge happened at all.  You may want to finish
+whatever you were in the middle of doing, and retry the same
+pull after you are done and ready.
I am not sure what two cases we were describing.  It could be that this
paragraph was taken from a mailing list message responding to a question
(e.g. "I got this merge failure message and my tree is screwed up.  Please
help me get back to a good state, I am lost...") without copying the
original sample failure scenario.

Re: [PATCH] Documentation/git-merge.txt: Expand the How Merge Works section

From: Petr Baudis <hidden>
Date: 2016-06-15 22:44:57

  Hi,

  I'm not sure if I should resend the updated patch, or if you already
included your comments yourself.

On Thu, Jul 17, 2008 at 11:17:22AM -0700, Junio C Hamano wrote:
Petr Baudis [off-list ref] writes:
quoted
+* `HEAD` is already contained in the merged commit. This is the
+  most common case especially when involved through 'git pull':
+  you are tracking an upstream repository, committed no local
+  changes and now you want to update to a newer upstream revision.
+  So-called "fast-forward merge" is performed, simply repointing
+  your `HEAD` (and index) to the merged commit; no extra merge
+  commit is created.
I'd suggest rewording the last three lines:

	Your `HEAD` (and the index) is updated to point the merged
							^ at
        commit, without creating an extra merge commit.  This is
        called "Fast-forward".
  Yes, that is better.
quoted
+Pre-flight requirements note
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In certain special cases, your index is
+allowed to be different from the tree of the `HEAD` commit.
Now this paragraph is moved far away from the original context that said
"your index must be clean before you start your merge", you would need to
re-introduce that in this sentenece:

	... tree of the `HEAD` before you run 'git-merge'.
  Done.

  I have to admit that I didn't even carefully read the rest of this
subsection, but I agree that we might as well update it when moving it
around already.
quoted
+... Also, your index entries
+may have differences from your `HEAD` commit that match
+the result of a trivial merge (e.g. you received the same patch
+from an external source to produce the same result as what you are
+merging).  For example, if a path did not exist in the common
+ancestor and your head commit but exists in the tree you are
+merging into your repository, and if you already happen to have
+that path exactly in your index, the merge does not have to
+fail.
I originally wrote the above paragraph purely for completeness, but I
wonder if this happens a lot in practice.  This is not something the user
can easily anticipate anyway, so we might want to drop this.
  I think that we can expect only users that have real interest in these
details to read through this, so I would keep it for the completeness.
quoted
+So in the above two "failed merge" case, you do not have to
+worry about loss of data --- you simply were not ready to do
+a merge, so no merge happened at all.  You may want to finish
+whatever you were in the middle of doing, and retry the same
+pull after you are done and ready.
I am not sure what two cases we were describing.  It could be that this
paragraph was taken from a mailing list message responding to a question
(e.g. "I got this merge failure message and my tree is screwed up.  Please
help me get back to a good state, I am lost...") without copying the
original sample failure scenario.
  Yes, I got confused by this too. I would perhaps simply drop this
paragraph altogether.

-- 
				Petr "Pasky" Baudis
GNU, n. An animal of South Africa, which in its domesticated state
resembles a horse, a buffalo and a stag. In its wild condition it is
something like a thunderbolt, an earthquake and a cyclone. -- A. Pierce
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help