Isaac.Truett.info
How to Use Git
- command-line
- know-your-tools
My opinionated guide to using git for version control.
Principles
- Developers are stewards of history
- Keep the log clean; protect its integrity
- What goes on master stays on master
- Never force push
- Tags are like photographs; snapshots of a moment in time
- Tag things you want to remember and remove them from HEAD – don’t leave them there “just in case” – it’ll last longer
- Branches are short and sweet, like a limerick
- … unless you maintain multiple versions of your product, in which case some of your branches are main-line for those versions
- All other branches: git in, make your changes, and git out
- Rebase is your friend
- No merge commits
- Fast-forward merging only
Open all sections
Start in the right place
-
How
Why
This will make sure that you're on the master branch, that master is up-to-date, and that any stray commits you have lying around in your local repository's master branch are placed on top of the remote version of history, as is Good and Proper in the stewardship of your code's history.
This config setting will make rebase the default behavior for
pull
, in case you forget to add the--rebase
flag.
Make a branch
-
How
Why
Making changes on a separate branch helps history stay clean by keeping all of your changes for a specific feature or bugfix together, giving you a place to amend or revert commits without leaving a trace in history, and finally submitting your changes for a review as part of a pull request process.
Stage your changes for commiting
-
How
Why
A quick shortcut to recursively add all of the changes in the current directory is
git all .
, but, by adding files individually, you have a chance to be thoughtful and make a deliberate decision about whether each file belongs in the commit. It can be tempting to take all of the changes at once, but we often end up touching many files during the development process and making changes that are not required in the final solution. These changes may be good changes to make, but if they aren't required for the current issue you're working on, it's probably best to make a separate commit.
Do a self-review
-
How
Why
diff
with the--cached
option will show you all of your staged (added), but not yet committed, changes. This is a good opportunity to review what you've done, and make sure that each line that changed is correct and appropriate to be committed at this time.
Commit your changes
-
How
Why
Be sure to add a thoughtful comment about the changes you are making. If you have a ticket tracking system, it can be very helpful to include a reference to the ticket you are working on at the start of the comment, like this:
[issue-123] Adds a third solo to correct for insufficient cowbell
Add the one little change you missed
-
How
Why
Sometimes, immediately after commiting changes, despite all the reviews, I do a
git status
and see a file I missed. Or I flip back to my editor and realize "Oh, if I change this, then I'm going to have to change that too." In these cases, there's no harm in modifying the commit I just made. I'lladd
the additonal changes and then use--amend
to alter the previous commit, combining my staged but uncommitted changes with the changes in the previous commit. So if my last commit added two files and I have one more file staged, then the commit with two files is replaced by a commit with all three. In the commit history it now looks like I committed all three at once. My intent is clear, and the history reflects that intent. No need for a commit that just says "oops, I missed one."
Catch up on changes in master
-
How
Make sure you have all of your changes committed, then:
Resolve merge conflicts during the rebase, if any, and then you're all caught up with master.
Why
This process first takes you back to the master branch, pulls and updates your local master branch with any changes from origin, then switches back to your branch and rebases, applying your changes on top of the new master history.
See everything you've changed compared with master
-
How
Why
This is especially handy after you've rebased on top of a new master branch HEAD to do a sanity check before submitting changes for a peer review. My branch may contain a number of separate commits, and this lets me see the changes holisticly
Recovering a lost commit
-
How
Search the reflog for your missing commit. It helps if you remember the message, or date and time of the commit. When you think you've found it, check out that commit:
Be careful! You are now "detached," meaning you are not at the HEAD of a branch. Commits made from here are not part of a branch. (Becoming detached is a common way of losing commits, in fact). Review the code at this point. If you've found your missing changes, then create a branch:
Now you can continue working from your recovered commit, merge those changes into another branch, or just leave the branch as it is, safe in the knowledge that your changes were not permanently lost.
Why
The reflog is similar to a branch's log. The commit log you get from
git log
shows the ancestry of the branch, the changes that incrementally brought it to this point. Instead of a sequential list of changes to files, the reflog shows the sequence of git commands that got you to the current state. The commit information (e.g., author, message, hash) is also there, and that's what helps us find our lost commits. We can narrow down the reflog further by piping the output intogrep
to filter it down to just the commits:
Share your changes
-
How
Why
All of your commits happen in your local repository. To share changes with anyone else, they have to be pushed or pulled from one repository to another. The way this typically works is that each developer pulls from a shared remote repository, refered to as origin, and then pushes their changes back to origin where others can then pull them down.
Need to see it in pictures? You can see branching in action with this interactive visual tutorial.