Skip to content

Commit ccef66b

Browse files
Junio C HamanoLinus Torvalds
authored andcommitted
[PATCH] read-tree: update documentation for 3-way merge.
This explains the new merge world order that formally assigns specific meaning to each of three tree-ish command line arguments. It also mentions -u option Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d4f8b39 commit ccef66b

File tree

1 file changed

+66
-24
lines changed

1 file changed

+66
-24
lines changed

Documentation/git-read-tree.txt

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,44 @@ git-read-tree - Reads tree information into the directory cache
99

1010
SYNOPSIS
1111
--------
12-
'git-read-tree' (<tree-ish> | -m <tree-ish1> [<tree-ish2> <tree-ish3>])"
12+
'git-read-tree' (<tree-ish> | [-m [-u]] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
13+
1314

1415
DESCRIPTION
1516
-----------
16-
Reads the tree information given by <tree> into the directory cache,
17+
Reads the tree information given by <tree-ish> into the directory cache,
1718
but does not actually *update* any of the files it "caches". (see:
1819
git-checkout-cache)
1920

20-
Optionally, it can merge a tree into the cache or perform a 3-way
21-
merge.
21+
Optionally, it can merge a tree into the cache, perform a
22+
fast-forward (i.e. 2-way) merge, or a 3-way merge, with the -m
23+
flag. When used with -m, the -u flag causes it to also update
24+
the files in the work tree with the result of the merge.
2225

2326
Trivial merges are done by "git-read-tree" itself. Only conflicting paths
2427
will be in unmerged state when "git-read-tree" returns.
2528

2629
OPTIONS
2730
-------
2831
-m::
29-
Perform a merge, not just a read
32+
Perform a merge, not just a read.
33+
34+
-u::
35+
After a successful merge, update the files in the work
36+
tree with the result of the merge.
3037

3138
<tree-ish#>::
3239
The id of the tree object(s) to be read/merged.
3340

3441

3542
Merging
3643
-------
37-
If '-m' is specified, "git-read-tree" performs 2 kinds of merge, a single tree
38-
merge if only 1 tree is given or a 3-way merge if 3 trees are
44+
If '-m' is specified, "git-read-tree" can performs 3 kinds of
45+
merge, a single tree merge if only 1 tree is given, a
46+
fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
3947
provided.
4048

49+
4150
Single Tree Merge
4251
~~~~~~~~~~~~~~~~~
4352
If only 1 tree is specified, git-read-tree operates as if the user did not
@@ -47,7 +56,7 @@ being read, the stat info from the cache is used. (In other words, the
4756
cache's stat()s take precedence over the merged tree's)
4857

4958
That means that if you do a "git-read-tree -m <newtree>" followed by a
50-
"git-checkout-cache -f -a", the "git-checkout-cache" only checks out
59+
"git-checkout-cache -f -u -a", the "git-checkout-cache" only checks out
5160
the stuff that really changed.
5261

5362
This is used to avoid unnecessary false hits when "git-diff-files" is
@@ -166,23 +175,18 @@ merge. The different stages represent the "result tree" (stage 0, aka
166175
"merged"), the original tree (stage 1, aka "orig"), and the two trees
167176
you are trying to merge (stage 2 and 3 respectively).
168177

169-
In fact, the way "git-read-tree" works, it's entirely agnostic about how
170-
you assign the stages, and you could really assign them any which way,
171-
and the above is just a suggested way to do it (except since
172-
"git-write-tree" refuses to write anything but stage0 entries, it makes
173-
sense to always consider stage 0 to be the "full merge" state).
174-
175-
So what happens? Try it out. Select the original tree, and two trees
176-
to merge, and look how it works:
178+
The order of stages 1, 2 and 3 (hence the order of three
179+
<tree-ish> command line arguments) are significant when you
180+
start a 3-way merge with an index file that is already
181+
populated. Here is an outline of how the algorithm works:
177182

178183
- if a file exists in identical format in all three trees, it will
179-
automatically collapse to "merged" state by the new git-read-tree.
184+
automatically collapse to "merged" state by git-read-tree.
180185

181186
- a file that has _any_ difference what-so-ever in the three trees
182187
will stay as separate entries in the index. It's up to "script
183188
policy" to determine how to remove the non-0 stages, and insert a
184-
merged version. But since the index is always sorted, they're easy
185-
to find: they'll be clustered together.
189+
merged version.
186190

187191
- the index file saves and restores with all this information, so you
188192
can merge things incrementally, but as long as it has entries in
@@ -201,11 +205,49 @@ to merge, and look how it works:
201205
matching "stage1" entry if it exists too. .. all the normal
202206
trivial rules ..
203207

204-
Incidentally - it also means that you don't even have to have a
205-
separate subdirectory for this. All the information literally is in
206-
the index file, which is a temporary thing anyway. There is no need to
207-
worry about what is in the working directory, since it is never shown
208-
and never used.
208+
You would normally use "git-merge-cache" with supplied
209+
"git-merge-one-file-script" to do this last step. The script
210+
does not touch the files in the work tree, and the entire merge
211+
happens in the index file. In other words, there is no need to
212+
worry about what is in the working directory, since it is never
213+
shown and never used.
214+
215+
When you start a 3-way merge with an index file that is already
216+
populated, it is assumed that it represents the state of the
217+
files in your work tree, and you can even have files with
218+
changes unrecorded in the index file. It is further assumed
219+
that this state is "derived" from the stage 2 tree. The 3-way
220+
merge refuses to run if it finds an entry in the original index
221+
file that does not match stage 2.
222+
223+
This is done to prevent you from losing your work-in-progress
224+
changes. To illustrate, suppose you start from what has been
225+
commited last to your repository:
226+
227+
$ JC=`cat .git/HEAD`
228+
$ git-checkout-cache -f -u -a $JC
229+
230+
You do random edits, without running git-update-cache. And then
231+
you notice that the tip of your "upstream" tree has advanced
232+
since you pulled from him:
233+
234+
$ git-fetch-script rsync://.... linus
235+
$ LT=`cat .git/MERGE_HEAD`
236+
237+
Your work tree is still based on your HEAD ($JC), but you have
238+
some edits since. Three-way merge makes sure that you have not
239+
added or modified cache entries since $JC, and if you haven't,
240+
then does the right thing. So with the following sequence:
241+
242+
$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
243+
$ git-merge-cache git-merge-one-file-script -a
244+
$ echo "Merge with Linus" | \
245+
git-commit-tree `git-write-tree` -p $JC -p $LT
246+
247+
what you would commit is a pure merge between $JC and LT without
248+
your work-in-progress changes, and your work tree would be
249+
updated to the result of the merge.
250+
209251

210252
See Also
211253
--------

0 commit comments

Comments
 (0)