[Notes] A Tale of Three Trees by @chacon
Here’s some more Strange Loop 2011 material–this time about a talk on git given by Scott Chacon (@chacon)!
In his talk, Scott focuses on demystifying git’s reset command through an explanation of git’s three trees: HEAD, index, and the working tree. Toward the end of the talk, he also includes some of Git’s plumbing goodies that can be useful in local scripts for automatic backup, cleaning past commits, and so forth.
Hope you enjoy the notes. As always, I typed quickly and so guarantee absolutely no accuracy. You might reference these notes with his slides (warning: PDF).
Trees
- Head
- Indirect pointer to the last commit
- Points to a tree
- Index
- Working Directory
- Tree Roles
- Last commit, next parent
- Index proposed next commit
- Could
git addeverything,rmall files, andgit commitwould still work just fine
- Could
- Work Dir sandbox
git statustells you the diff of the three trees
git reset
- A tool to manipulate these three trees
- Path Form:
git reset [file]- Opposite of
git add [file] - Takes entry from
HEADand make index look like that - Lets you manipulate your index without touching your working directory.
- Opposite of
- Commit form:
git reset [commit]- Does three things in order. The option determines where in this process it stops.
--soft: moveHEADto target- Moving the branch to somewhere else. Does not change index or working directory; just changes where the branch points.
git reset --soft HEAD~HEAD~: parent ofHEAD- Undoes results of last commit.
[--mixed]: then copy to index- Takes what
HEADis pointing at and makes your index look like that.
- Takes what
--hard— then copy to work dir- Touches your working directory
- Path Form:
- Can use this to squash the last two commits into one
git reset --soft HEAD~2; git commit- Moves
HEADback tw ocommits, keep index
- Moves
- Awesome for staging your work in progress and then making one nice, beautiful commit
git checkoutgit checkout [commit] [path]git checkout [commit]- If you’re in a dev branch and have made some commits:
git reset masterwill move your index to where the branch startedgit checkout masterwill moveHEADto point to master
- reset vs. checkout
- Patchy work
git add --patch [file]git reset --patch (commit) [file]git checkout --patch (commit) [file]- Revert parts of a file for commit
Tidbits
git add -p- Uses the index tree as a staging area for partial addition
git commit --amend==git reset --soft HEAD~; git commit ...git log --stat (branch)
The Plumbing Commands
- A summary of the below commands
rev-parse- Take any string you give it and tell you its SHA. E.g.,
git rev-parse origin/master git rev-parse master~163^2~3^2— walks backwards, does some cool stuff. Figures out its SHA.- Can do ranges:
git rev-parse master~163^2~3^2..origin/master
- Take any string you give it and tell you its SHA. E.g.,
hash-object- Use git as a raw key-value store
git hash-object -w ~/.sshid_rsa.pubecho 'my awesome value' | git hash-object -w --stdin- Will return SHA and write into database
ls-filesgit ls-files -s: shows you your staging area
read-tree- Reads a tree value into your index at a raw value
git ls-files -s # show index git ls-files -r HEAD # show index git read-tree HEAD~2 # basically same as git reset
- Reads a tree value into your index at a raw value
write-tree- Takes whatever your index looks like and writes it out as a tree object.
git write-tree: tells you the tree that a commit would make if you commited it.- Does not commit.
commit-treeecho 'my commit message' | git commit-tree- Commits without
git commit
update-ref- Part of
git branchmechanism - Updates your reflog as well
git update-ref refs/heads/newbranch
- Part of
symbolic-ref- Update HEAD itself
git symbolic-ref HEAD refs/heads/newbranch
- Example usage
- Could make an auto-backup system for your working directory
- Publish documentation to another branch
- These are all under the rules that you shouldn’t mess with history if you’ve
already pushed that to people.
- So, use this stuff locally.