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 rabasing 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: README.md
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 for similar content and follow me on Twitter for more git (and general programming) tips.
Top comments (2)
I would not recommend using soft reset to fix commits on the wrong branch, especially with multiple commits. You end up with all the changes back to uncommitted, and having to sort through them in order to recreate the commits.
Say you meant for a series of commits,
commit1
thrucommit2
, to be onbranch1
, but accidentally made them onbranch2
, to fix it, simply do:Great article... and I can't believe I didn't know about renaming a branch until this moment 🤦♀️🤦♀️🤦♀️