Issue 03

5 scary Git commands you'll eventually have use for

They won't bite - don't be afraid

Jun 30, 2022 · 5 minute read

Version control is magical.

I strongly believe everyone should learn how to use it - not just developers. How many times did you complete homework back at school and create arrays of filenames to denote just how final that piece of work was?

Today, in modern web development, Git is an absolute pre-requisite. But it's still shocking to see just how many experienced developers are just scratching the surface of what Git can do for you.

In this blog post I hope to unearth at least one useful Git command you perhaps haven't come across or would even think to use.

git rebase

Git rebasing is boils down to moving or combining a sequence of commits into a new base commit. It essentially appears like you've created your branch from a different commit base - extremely useful if you've been working on a branch for a while, you've diverged off of the main branch for a while and you run into conflicts when you try and merge back in.

It works something like this:

git checkout main # change to main branch
git pull origin main 
git checkout - # go back to last branch (feature branch)
git rebase main
# fix conflicts
git add .
git rebase --continue # until all changes are in

You can also use --interactive mode for rebasing which will let you manually select which commits you want to ignore throughout - helpful if you've made a commit purely to add some debugging and forgotten before committing.

Now, some of you might be thinking you can just git pull origin main in your branch and resolve the merge conflicts in an even easier fashion. While they are both similar there's one massive difference that you want to keep in mind here:

  • git pull will create a new commit that combines the two branches together
  • git rebase will move the commits of one branch on top of the other

You can also use git pull --rebase to pull using rebase which can be great and save you a lot of time. However

git rebase will essentially keep your git history clean.

Why is this important?

It means you can safely and effectively use our next arcane power: git bisect.

git bisect

git bisect uses binary search to find a commit that introduced some new unwanted functionality (read: bug).

It kind of works like this:

Imagine you're digging for the commit that broke a feature that we knew was working in commit 0cd429f02 (or a tagged commit), and somewhere along the way we broke something and a test is failing.

We can use git bisect to narrow down the commits and help us identify the culprit like so:

git bisect start
git bisect bad
git bisect good 0cd429f02

Note: You can use git bisect reset to jump out of this.

Once you've specified a good and a bad commit, bisect will find a commit in the middle of that range, check it out and give you some information regarding how many possible steps are left to split through.

Now that you're in your checked out commit you should run your tests and assuming it works, you can inform bisect of that by typing git bisect good, or tell bisect that that particular version is failing with git bisect bad.

Repeat the above steps and eventually you'll run out of revisions to test - bisect will then spit out the description of the first bad commit with a nice little summary - and there's your buggy commit. ✨

git stash

Stashing is used to take your uncommitted changes (including staged) and temporarily "stash" them away for later.

Extremely useful when you're not quite ready to commit a change, but need to move to another branch for some reason - maybe there's a bug you need to investigate.

You can stash your content like this:

git status

Changes not staged for commit:
	modified:   mix.exs
	modified:   test/inspyre_web/live/story_live_test.exs

no changes added to commit (use "git add" and/or "git commit -a")

git stash

git status

On branch main
Your branch is up to date with 'origin/main'.

Like magic your changes are seemingly gone.. or are they?

If you run git stash list you'll see a log of previously stashed events alongside the branch you were operating on and the last commit in that log.

Running git stash apply will take the last stashed set of changes and apply them to your current branch but will not remove them from your stash list. If you know you won't need them this one time stash you'll want to use git stash pop to apply the changes and pop them out of your stash list.

git reset --soft HEAD^N

Have you ever accidentally thought you changed branch but really you were still in the last feature you were working on?

Have you committed multiple times?

Whoops. It's cool - we can fix that.

Use git reset --soft HEAD^N where N is the number of commits you want to un-commit to bring them back to you. From here you can stash or move to another branch and commit them there.

Be careful not to type --hard though. That'll trash unsaved changes for good.

git reflog

Gits secret weapon / time capsule.

git reflog will give you a list of every single thing you've done in git across every single branch.

If you've accidentally ended up in a state you weren't expecting to be in, deleted things, merged things accidentally or can't figure out what's happened, reach for git reflog (at least before you trash everything and re-clone your repo).

git branch -M BONUS

This one is simple but effective - and one I know several devs resort to deleting and recreating a branch to solve! 🤯

Renaming a branch!

Simply type git branch -M <new_branch_name> to set your new branch name for the branch your currently in.

That's all folks.

Hopefully that was useful for some - subscribe to my Substack below for similar content and follow me on Twitter for more git (and general programming) tips.

Enjoyed this content?

Want to learn and master LiveView?

Check out the book I'm writing

The Phoenix LiveView Cookbook

Sign up to my substack to be emailed about new posts