Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a basic example of the read-tree command usage

Tags:

git

I was having an issue with renaming a file and was given a solution which included two git commands - git read-tree -i HEAD and git checkout-index -a -f. I seems to have figured out what the second one does and tested it, but I can't grasp why I would need the first one even for the simplest case. I thought that it somehow could substitue git add command and add a file to index, however when I created a new file and run the command and then checked the contents of index with ls-files --staged it didn't show this files as added, so probably my assumption about the purpose of the command is wrong. I also visited the manual page but still don't understand why I would need that command.

like image 240
Max Koretskyi Avatar asked Mar 20 '14 13:03

Max Koretskyi


2 Answers

git read-tree goes like this:

  1. Parses a "tree-ish" passed to it to find an object existing in the Git repository describing a tree.

    A tree is what represents a directory in Git: this kind of object lists the SHA-1 and filesystem names of blobs (files) and nested trees (of nested directories) comprising the tree. Each commit references exactly one tree which represents the state of the top-level project directory itself.

    A "tree-ish" is a specification whish Git is able to parse down to the name of a tree object. For instance, HEAD is first parsed as the name of a reference, then the branch it points to is chased to get its tip commit, then it's parsed to get the name of its tree object.

  2. Reads the acquired tree object, recursively, and populates the index with the information on these objects. The index does not contain the actual data of the files—only meta information on them.

    IOW, the index is like a miniature filesystem kept in a single file. Its format is optimized for super-fast access over a huge nested sets of files.

Now another command, git checkout-index can be used to bring the work tree in sync with the index. Commands like git checkout <commit> do exactly this: call git read-tree to populate the index and then git checkout-index to sync the work tree with it.

That's the basics. The command is able to do more than that:

  • If passed the -m command line option, it's able to merge the tree(s) passed to it into the index.
  • It's able to read the indicated tree in a way so that its files appear (in the index) in a subdirectory of the project (via --prefix).
  • It's able to empty the index (via --empty).

In the simplest form we've called it when we've been dealing with your original problem, it just replaced the contents of the index with what was referenced by HEAD at the moment.

Note that git read-tree is a plumbing command, not intended to be routinely used by users. It's called automatically when you do things like git checkout <commit>. I've advised to call it directly because who knows if running git checkout HEAD would really update your index or it would decide that since it anyway reflects the state of the HEAD nothing should be done. Calling it by hand ensured the index started to contain exactly the state we needed. In the general case you don't need this program and hence that's why it's hard to come up with a trivial usage example.

like image 86
kostix Avatar answered Oct 25 '22 06:10

kostix


The read-tree command takes a git tree object and copies its state into the index. In your case you are taking the tree currently marked as HEAD and resetting the index to match this tree - that is equivalent to git reset --mixed HEAD. The first command can be used when you need to bring in a discontinuous history from some other repository (see this blog entry) such as a converted CVS repository. Once you have the index in a state that matches what you need you can create a commit as normal. The read-tree command is not going to be like add - it will not look at anything in the current working folder set. It is doing reset.

like image 40
patthoyts Avatar answered Oct 25 '22 06:10

patthoyts