X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=Documentation%2Fgit-read-tree.txt;h=11bd9c0adc5517ef1aadc76abdb8dfb0827c27b0;hb=HEAD;hp=7db5fb579597373128c9cbb44ef02adf5e9da8a0;hpb=72e5890b68e7199d92620d3bba91fa36dd259404;p=git.git diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 7db5fb57..11bd9c0a 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -3,32 +3,39 @@ git-read-tree(1) NAME ---- -git-read-tree - Reads tree information into the directory cache +git-read-tree - Reads tree information into the index SYNOPSIS -------- -'git-read-tree' ( | [-m [-u|-i]] [ []]) +'git-read-tree' ( | [[-m [--aggressive] | --reset | --prefix=] [-u | -i]] [ []]) DESCRIPTION ----------- -Reads the tree information given by into the directory cache, +Reads the tree information given by into the index, but does not actually *update* any of the files it "caches". (see: -git-checkout-index) +gitlink:git-checkout-index[1]) -Optionally, it can merge a tree into the cache, perform a -fast-forward (i.e. 2-way) merge, or a 3-way merge, with the -m -flag. When used with -m, the -u flag causes it to also update +Optionally, it can merge a tree into the index, perform a +fast-forward (i.e. 2-way) merge, or a 3-way merge, with the `-m` +flag. When used with `-m`, the `-u` flag causes it to also update the files in the work tree with the result of the merge. -Trivial merges are done by "git-read-tree" itself. Only conflicting paths -will be in unmerged state when "git-read-tree" returns. +Trivial merges are done by `git-read-tree` itself. Only conflicting paths +will be in unmerged state when `git-read-tree` returns. OPTIONS ------- -m:: - Perform a merge, not just a read. + Perform a merge, not just a read. The command will + refuse to run if your index file has unmerged entries, + indicating that you have not finished previous merge you + started. + +--reset:: + Same as -m, except that unmerged entries are discarded + instead of failing. -u:: After a successful merge, update the files in the work @@ -43,6 +50,27 @@ OPTIONS trees that are not directly related to the current working tree status into a temporary index file. +--aggressive:: + Usually a three-way merge by `git-read-tree` resolves + the merge for really trivial cases and leaves other + cases unresolved in the index, so that Porcelains can + implement different merge policies. This flag makes the + command to resolve a few more cases internally: ++ +* when one side removes a path and the other side leaves the path + unmodified. The resolution is to remove that path. +* when both sides remove a path. The resolution is to remove that path. +* when both sides adds a path identically. The resolution + is to add that path. + +--prefix=/:: + Keep the current index contents, and read the contents + of named tree-ish under directory at ``. The + original index file cannot have anything at the path + `` itself, and have nothing in `/` + directory. Note that the `/` value must end + with a slash. + :: The id of the tree object(s) to be read/merged. @@ -50,7 +78,7 @@ OPTIONS Merging ------- -If '-m' is specified, "git-read-tree" can perform 3 kinds of +If `-m` is specified, `git-read-tree` can perform 3 kinds of merge, a single tree merge if only 1 tree is given, a fast-forward merge with 2 trees, or a 3-way merge if 3 trees are provided. @@ -59,23 +87,23 @@ provided. Single Tree Merge ~~~~~~~~~~~~~~~~~ If only 1 tree is specified, git-read-tree operates as if the user did not -specify '-m', except that if the original cache has an entry for a +specify `-m`, except that if the original index has an entry for a given pathname, and the contents of the path matches with the tree -being read, the stat info from the cache is used. (In other words, the -cache's stat()s take precedence over the merged tree's). +being read, the stat info from the index is used. (In other words, the +index's stat()s take precedence over the merged tree's). -That means that if you do a "git-read-tree -m " followed by a -"git-checkout-index -f -u -a", the "git-checkout-index" only checks out +That means that if you do a `git-read-tree -m ` followed by a +`git-checkout-index -f -u -a`, the `git-checkout-index` only checks out the stuff that really changed. -This is used to avoid unnecessary false hits when "git-diff-files" is -run after git-read-tree. +This is used to avoid unnecessary false hits when `git-diff-files` is +run after `git-read-tree`. Two Tree Merge ~~~~~~~~~~~~~~ -Typically, this is invoked as "git-read-tree -m $H $M", where $H +Typically, this is invoked as `git-read-tree -m $H $M`, where $H is the head commit of the current repository, and $M is the head of a foreign tree, which is simply ahead of $H (i.e. we are in a fast forward situation). @@ -88,7 +116,7 @@ the following: 2. The user wants to fast-forward to $M. -In this case, the "git-read-tree -m $H $M" command makes sure +In this case, the `git-read-tree -m $H $M` command makes sure that no local change is lost as the result of this "merge". Here are the "carry forward" rules: @@ -96,7 +124,7 @@ Here are the "carry forward" rules: ------------------------------------------------------- 0 nothing nothing nothing (does not happen) 1 nothing nothing exists use M - 2 nothing exists nothing remove path from cache + 2 nothing exists nothing remove path from index 3 nothing exists exists use M clean I==H I==M @@ -109,7 +137,7 @@ Here are the "carry forward" rules: 8 yes N/A no nothing exists fail 9 no N/A no nothing exists fail - 10 yes yes N/A exists nothing remove path from cache + 10 yes yes N/A exists nothing remove path from index 11 no yes N/A exists nothing fail 12 yes no N/A exists nothing fail 13 no no N/A exists nothing fail @@ -128,20 +156,20 @@ Here are the "carry forward" rules: 20 yes yes no exists exists use M 21 no yes no exists exists fail -In all "keep index" cases, the cache entry stays as in the +In all "keep index" cases, the index entry stays as in the original index file. If the entry were not up to date, git-read-tree keeps the copy in the work tree intact when operating under the -u flag. When this form of git-read-tree returns successfully, you can see what "local changes" you made are carried forward by running -"git-diff-index --cached $M". Note that this does not -necessarily match "git-diff-index --cached $H" would have +`git-diff-index --cached $M`. Note that this does not +necessarily match `git-diff-index --cached $H` would have produced before such a two tree merge. This is because of cases 18 and 19 --- if you already had the changes in $M (e.g. maybe -you picked it up via e-mail in a patch form), "git-diff-index ---cached $H" would have told you about the change before this -merge, but it would not show in "git-diff-index --cached $M" +you picked it up via e-mail in a patch form), `git-diff-index +--cached $H` would have told you about the change before this +merge, but it would not show in `git-diff-index --cached $M` output after two-tree merge. @@ -150,35 +178,43 @@ output after two-tree merge. Each "index" entry has two bits worth of "stage" state. stage 0 is the normal one, and is the only one you'd see in any kind of normal use. -However, when you do "git-read-tree" with three trees, the "stage" +However, when you do `git-read-tree` with three trees, the "stage" starts out at 1. This means that you can do - git-read-tree -m +---------------- +$ git-read-tree -m +---------------- and you will end up with an index with all of the entries in "stage1", all of the entries in "stage2" and all of the - entries in "stage3". + entries in "stage3". When performing a merge of another +branch into the current branch, we use the common ancestor tree +as , the current branch head as , and the other +branch head as . -Furthermore, "git-read-tree" has special-case logic that says: if you see +Furthermore, `git-read-tree` has special-case logic that says: if you see a file that matches in all respects in the following states, it "collapses" back to "stage0": - stage 2 and 3 are the same; take one or the other (it makes no - difference - the same work has been done on stage 2 and 3) + difference - the same work has been done on our branch in + stage 2 and their branch in stage 3) - stage 1 and stage 2 are the same and stage 3 is different; take - stage 3 (some work has been done on stage 3) + stage 3 (our branch in stage 2 did not do anything since the + ancestor in stage 1 while their branch in stage 3 worked on + it) - stage 1 and stage 3 are the same and stage 2 is different take - stage 2 (some work has been done on stage 2) + stage 2 (we did something while they did nothing) -The "git-write-tree" command refuses to write a nonsensical tree, and it +The `git-write-tree` command refuses to write a nonsensical tree, and it will complain about unmerged entries if it sees a single entry that is not stage 0. -Ok, this all sounds like a collection of totally nonsensical rules, +OK, this all sounds like a collection of totally nonsensical rules, but it's actually exactly what you want in order to do a fast merge. The different stages represent the "result tree" (stage 0, aka "merged"), the original tree (stage 1, aka "orig"), and the two trees @@ -199,7 +235,7 @@ populated. Here is an outline of how the algorithm works: - the index file saves and restores with all this information, so you can merge things incrementally, but as long as it has entries in - stages 1/2/3 (ie "unmerged entries") you can't write the result. So + stages 1/2/3 (i.e., "unmerged entries") you can't write the result. So now the merge algorithm ends up being really simple: * you walk the index in order, and ignore all entries of stage 0, @@ -214,12 +250,10 @@ populated. Here is an outline of how the algorithm works: matching "stage1" entry if it exists too. .. all the normal trivial rules .. -You would normally use "git-merge-index" with supplied -"git-merge-one-file" to do this last step. The script -does not touch the files in the work tree, and the entire merge -happens in the index file. In other words, there is no need to -worry about what is in the working directory, since it is never -shown and never used. +You would normally use `git-merge-index` with supplied +`git-merge-one-file` to do this last step. The script updates +the files in the working tree as it merges each path and at the +end of a successful merge. When you start a 3-way merge with an index file that is already populated, it is assumed that it represents the state of the @@ -230,33 +264,54 @@ merge refuses to run if it finds an entry in the original index file that does not match stage 2. This is done to prevent you from losing your work-in-progress -changes. To illustrate, suppose you start from what has been -commited last to your repository: +changes, and mixing your random changes in an unrelated merge +commit. To illustrate, suppose you start from what has been +committed last to your repository: - $ JC=`cat .git/HEAD` - $ git-checkout-index -f -u -a $JC +---------------- +$ JC=`git-rev-parse --verify "HEAD^0"` +$ git-checkout-index -f -u -a $JC +---------------- You do random edits, without running git-update-index. And then you notice that the tip of your "upstream" tree has advanced since you pulled from him: - $ git-fetch rsync://.... linus - $ LT=`cat .git/MERGE_HEAD` +---------------- +$ git-fetch git://.... linus +$ LT=`cat .git/FETCH_HEAD` +---------------- Your work tree is still based on your HEAD ($JC), but you have some edits since. Three-way merge makes sure that you have not -added or modified cache entries since $JC, and if you haven't, +added or modified index entries since $JC, and if you haven't, then does the right thing. So with the following sequence: - $ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT - $ git-merge-index git-merge-one-file -a - $ echo "Merge with Linus" | \ - git-commit-tree `git-write-tree` -p $JC -p $LT +---------------- +$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT +$ git-merge-index git-merge-one-file -a +$ echo "Merge with Linus" | \ + git-commit-tree `git-write-tree` -p $JC -p $LT +---------------- -what you would commit is a pure merge between $JC and LT without +what you would commit is a pure merge between $JC and $LT without your work-in-progress changes, and your work tree would be updated to the result of the merge. +However, if you have local changes in the working tree that +would be overwritten by this merge,`git-read-tree` will refuse +to run to prevent your changes from being lost. + +In other words, there is no need to worry about what exists only +in the working tree. When you have local changes in a part of +the project that is not involved in the merge, your changes do +not interfere with the merge, and are kept intact. When they +*do* interfere, the merge does not even start (`git-read-tree` +complains loudly and fails without modifying anything). In such +a case, you can simply continue doing what you were in the +middle of doing, and when your working tree is ready (i.e. you +have finished your work-in-progress), attempt the merge again. + See Also --------