blob: c4bde6509e5a2f652dca9345a3a28e9e674c216a [file] [log] [blame]
git-read-tree - Reads tree information into the index
'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>]
but does not actually *update* any of the files it "caches". (see:
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
Trivial merges are done by 'git read-tree' itself. Only conflicting paths
will be in unmerged state when 'git read-tree' returns.
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
Same as -m, except that unmerged entries are discarded
instead of failing.
After a successful merge, update the files in the work
tree with the result of the merge.
Usually a merge requires the index file as well as the
files in the working tree to be up to date with the
current head commit, in order not to lose local
changes. This flag disables the check with the working
tree and is meant to be used when creating a merge of
trees that are not directly related to the current
working tree status into a temporary index file.
Check if the command would error out, without updating the index
nor the files in the working tree for real.
Show the progress of checking files out.
Restrict three-way merge by 'git read-tree' to happen
only if there is no file-level merging required, instead
of resolving merge for trivial cases and leaving
conflicting files unresolved in the index.
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 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 add a path identically. The resolution
is to add that path.
Keep the current index contents, and read the contents
of the named tree-ish under the directory at `<prefix>`.
The command will refuse to overwrite entries that already
existed in the original index file. Note that the `<prefix>/`
value must end with a slash.
When running the command with `-u` and `-m` options, the
merge result may need to overwrite paths that are not
tracked in the current branch. The command usually
refuses to proceed with the merge to avoid losing such a
path. However this safety valve sometimes gets in the
way. For example, it often happens that the other
branch added a file that used to be a generated file in
your branch, and the safety valve triggers when you try
to switch to that branch after you ran `make` but before
running `make clean` to remove the generated file. This
option tells the command to read per-directory exclude
file (usually '.gitignore') and allows such an untracked
but explicitly ignored file to be overwritten.
Instead of writing the results out to `$GIT_INDEX_FILE`,
write the resulting index in the named file. While the
command is operating, the original index file is locked
with the same mechanism as usual. The file must allow
created next to the usual index file; typically this
means it needs to be on the same filesystem as the index
file itself, and you need write permission to the
directories the index file and index output file are
located in.
Disable sparse checkout support even if `core.sparseCheckout`
is true.
If `-m` is specified, 'git read-tree' can perform 3 kinds of
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 index has an entry for a
That means that if you do a `git read-tree -m <newtree>` 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'.
Two Tree Merge
Typically, this is invoked as `git read-tree -m $H $M`, where $H
fast-forward situation).
When two trees are specified, the user is telling 'git read-tree'
the following:
the user may have local changes in them since $H.
In this case, the `git read-tree -m $H $M` command makes sure
refer to the presence of a path in the specified commit:
I H M Result
0 nothing nothing nothing (does not happen)
1 nothing nothing exists use M
2 nothing exists nothing remove path from index
H == M keep index otherwise
exists, fail
H != M
clean I==H I==M
4 yes N/A N/A nothing nothing keep index
5 no N/A N/A nothing nothing keep index
6 yes N/A yes nothing exists keep index
7 no N/A yes nothing exists keep index
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 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
clean (H==M)
14 yes exists exists keep index
15 no exists exists keep index
16 yes no no exists exists fail
17 no no no exists exists fail
18 yes no yes exists exists keep index
19 no no yes exists exists keep index
20 yes yes no exists exists use M
21 no yes no exists exists fail
'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
`git diff-index --cached $M`. Note that this does not
necessarily match what `git diff-index --cached $H` would have
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 the two-tree merge.
3-Way Merge
However, when you do 'git read-tree' with three trees, the "stage"
starts out at 1.
This means that you can do
branch into the current branch, we use the common ancestor tree
branch head as <tree3>.
Furthermore, 'git read-tree' has special-case logic that says: if you see
"collapses" back to "stage0":
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
ancestor in stage 1 while their branch in stage 3 worked on
- stage 1 and stage 3 are the same and stage 2 is different take
stage 2 (we did something while they did nothing)
The 'git write-tree' command refuses to write a nonsensical tree, and it
stage 0.
populated. Here is an outline of how the algorithm works:
- if a file exists in identical format in all three trees, it will
automatically collapse to "merged" state by 'git read-tree'.
- a file that has _any_ difference what-so-ever in the three trees
merged version.
- the index file saves and restores with all this information, so you
now the merge algorithm ends up being really simple:
* you walk the index in order, and ignore all entries of stage 0,
since they've already been done.
original tree), and you remove that entry.
trivial rules ..
You would normally use 'git merge-index' with supplied
'git merge-one-file' to do this last step. The script updates
end of a successful merge.
populated, it is assumed that it represents the state of the
changes unrecorded in the index file. It is further assumed
file that does not match stage 2.
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:
You do random edits, without running 'git update-index'. And then
since you pulled from him:
$ git fetch git://.... linus
$ LT=`git rev-parse FETCH_HEAD`
then does the right thing. So with the following sequence:
$ echo "Merge with Linus" | \
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.
*do* interfere, the merge does not even start ('git read-tree'
complains loudly and fails without modifying anything). In such
Sparse checkout
"Sparse checkout" allows populating the working directory sparsely.
It uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell
'git read-tree' and other merge-based commands ('git merge', 'git
checkout'...) can help maintaining the skip-worktree bitmap and working
directory update. `$GIT_DIR/info/sparse-checkout` is used to
define the skip-worktree reference bitmap. When 'git read-tree' needs
While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
files are in, you can also specify what files are _not_ in, using
negate patterns. For example, to remove the file `unwanted`:
Another tricky thing is fully repopulating the working directory when you
no longer want sparse checkout. You cannot just disable "sparse
directory with the `$GIT_DIR/info/sparse-checkout` file content as
Then you can disable sparse checkout. Sparse checkout support in 'git
read-tree' and similar commands is disabled by default. You need to
turn `core.sparseCheckout` on in order to have sparse checkout
linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
Part of the linkgit:git[1] suite