Minimalist git

git clone git@github.com:bengarvey/lineage.git
cd lineage
git checkout -b bg-branch-name

# Make some code changes

git commit -am "Describe the changes"
git push origin bg-branch-name

# Write a great pull request description in github

git pull origin main
git push origin bg-branch-name

You only need a few git commands. They are checkout, push, pull, commit, clone, add, branch, reset, and mergetool.

If you are using github, perform all merges and reverts using the web UI. 

Clone

Create new repos using the github UI and clone them like this:

git clone git@github.com:bengarvey/lineage.git
cd lineage

Checkout

Branches are the heart of git. It’s how you keep your changes separate from the original code. Checkout a new branch like this:

git checkout -b bg-branch-name

My initials are bg, so I prefix all my branch names with bg-. This keeps all my branch names unique when working with others. Your collaborators should do this, too, so don’t hire anyone else with the same initials. The -b option tells git this is a new branch. If you ever want to come back to this branch later, omit the -b like this.

git checkout bg-branch-name

Branch names should be short and specific. If it’s a bug fix, suffix it with -fix.

Good branch names
bg-user-validation
bg-user-form-tooltips
bg-email-casing-fix

Bad branch names
bg-fix-2
bg-add-tests
bg-email-duplication-and-onboarding-fixes-from-product-meeting-fix

Add

Git doesn’t see every file in your directory until you add it. Add files to git like this:

git add app/controllers/users_controller.rb

Do this for every file individually. There are shortcuts to adding many files at once, but you’ll learn them when you need to.

Status

Status helps you figure out which branch you are on, which files you have changed, and which files need to be added to git.

git status

Commit

Applies the changes to your branch. They are only committed locally for now, so the copy on your dev machine is out of sync with the remote repository (eg. github).

git commit -am "Made email casing consistent during onboarding"

The -a option adds changed files to the commit and -m lets you add a commit message. There are many opinions about commit messages and how detailed they should be.

I set up github to squash all commits when merging a pull request into one merge commit, which erases all the commit messages. This is easier than having a clean commit history. Instead you should write a very detailed pull request description including screenshots, steps to reproduce and test the change, and your thought process for the change.

Push

Once you’ve committed your changes, send them back to the remote repository like this:

git push origin bg-branch-name

The only way you can really screw up using git is if you use git push with the –force or -f flag. I’ve used git every day for the last 12 years or so and I never have to use git push –force. I’ve seen many engineers accidentally force push and break stage or production environments. Something is wrong if you’re doing it regularly

Reset

Occasionally you’ll get in a state where you need to undo a bunch of changes you made. Git has a nice command for getting putting all your files back to the last commit you made.

git reset --hard

Be careful, you can’t undo this! It will remove and possibly delete files that git is managing, but it’s useful. You can also use reset to set your branch back to any commit in the past, but you don’t need it for minimalist git. Just reset back to the previous commit and continue on from there.

Branch

Branch helps you find or delete your branches. Combine it with grep to find what you need. For example, this will return all your local branches whose name contains email.

git branch | grep "email"

You can also use branch to delete a branch locally. It doesn’t delete it from the remote repository so sometimes it’s a good way to reset something that really got into a bad state. The code below checks out the main branch (you can’t delete the current branch), deletes the one you were working on and then checks it out again from the remote repository. 

git checkout main
git branch -D branch-name
git checkout branch-name

Mergetool

The scariest of all the commands required for minimalist git, but it’s not too bad. First configure git to use your preferred editor. I like vim. You only have to run these once.

git config --global merge.tool vimdiff 
git config --global merge.conflictstyle diff3 

And when you have a merge conflict, run the following:

git mergetool

Resolving merge conflicts is out of scope for this post, but this post looks is a good explanation.  You’re simply telling git which sections of code to pick from two options. Delete the code you don’t need and the dividers inserted by git. 

Commands to avoid

git rebase creates some problems working with other developers, because it’s easy to rewrite the commit history and remove changes made by someone else or apply them in the wrong order. 

git push –force is one of the only git commands that can break a perfectly good remote branch. 

Last thoughts

Git is the closest thing we have to software from the future. I wrote Minimalist Git because I’ve seen too many developers get lost in its advanced features and I wanted to show there is a simpler way to be productive and keep your codebase safe.

Use git in a way that’s productive for you. Not even everyone on my team at Common Paper agrees with me, but if you ever get really stuck, there’s always Oh, Shit, Git!?!


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *