Five Git commands that get you out of trouble

Leonardo Gurgitano5 minLeer en español

A concrete structure whose volumes separate and meet again.
A concrete structure whose volumes separate and meet again.

Almost all of us use the same four Git commands all the time: add, commit, push, pull. They are enough for an ordinary day.

The trouble starts when something goes wrong. That is usually when people copy the folder somewhere else just in case, clone the repository again, or paste their changes by hand into a new file.

These five commands solve those situations directly. You do not need to memorise them: it is enough to know they exist so you can look them up when the moment comes.

1. git reflog — recover what you deleted

When: you did something that destroyed work. One reset --hard too many, a deleted branch, a rebase that went wrong. The commits seem to be gone.

Git keeps a record of every place you have been, even when nothing points there any more:

git reflog
a3f21c9 HEAD@{0}: reset: moving to HEAD~3
8b4d012 HEAD@{1}: commit: add email validation
1c9e5a7 HEAD@{2}: commit: fix shipping calculation

There it is, 8b4d012, the commit you thought you had lost. To go back:

git reset --hard 8b4d012

The part worth knowing: Git does not delete commits right away. It keeps them for about thirty days even when nothing references them. Almost everything you think you lost is still there.

This is the command that has got me out of trouble the most times, and the one most people do not know exists.

2. git bisect — find when it broke

When: something worked two weeks ago and does not work now. There are a hundred and forty commits in between and you have no idea which one did it.

The manual alternative is trying commits at random. bisect does it by binary search: seven steps to check a hundred and forty commits.

git bisect start
git bisect bad                # the current one is broken
git bisect good v1.4.0        # this version worked

Git leaves you standing on a commit in the middle. You test it, and tell Git how it went:

git bisect good     # or "git bisect bad"

Repeat about seven times and it tells you exactly which one it was:

8b4d0129a3f21c9e5a7b4d012 is the first bad commit

When you are done, git bisect reset puts you back where you were.

The trick that makes it automatic: if you can write a command that exits with an error when things are broken, Git does the whole thing on its own.

git bisect start HEAD v1.4.0
git bisect run npm test

You go get a coffee and come back with the guilty commit identified.

3. git revert — undo something you already pushed

When: you pushed a commit that breaks production and it has to go now.

The temptation is reset --hard and push --force. Do not do that on a shared branch: it rewrites history that other people have already pulled, and the whole team’s next pull will break.

revert creates a new commit that undoes the changes of the previous one:

git revert a3f21c9

History stays intact and grows forward. Nobody has to do anything special.

The difference in one line: reset pretends it never happened; revert leaves a record that it happened and that you undid it. On a shared branch, always revert.

4. git stash — put your work aside without committing it

When: you are halfway through something and an urgent task comes up. Your changes are not ready for a commit, but you need to switch branches.

git stash push -m "validation half done"
git switch main          # now for the urgent thing
# ... you fix it ...
git switch my-branch
git stash pop            # your changes come back

Two things almost nobody knows, and that save you a surprise:

New files are not saved by default. If you created a file and have not run git add on it yet, stash ignores it and it stays where it is. To include them:

git stash push -u -m "with new files"

pop deletes the stash, apply keeps it. If you are not sure it will apply cleanly, use apply first and delete it afterwards with git stash drop.

5. git add -p — commit only part of what you changed

When: you touched a file to fix a bug, and along the way you also fixed some indentation and renamed a variable. You want the commit to contain only the fix.

git add -p file.js

Git shows you each block of changes and asks what to do:

Stage this hunk [y,n,q,a,d,s,e,?]?

y includes it, n skips it, and s splits a large block into smaller ones if they came out mixed together.

It is not an emergency command like the other four, but it is the one that improves your commits the most. A commit that does one single thing is understandable at a glance six months later — and it can be reverted without dragging along changes that had nothing to do with it.

What these five have in common

None of them is used every day. All of them show up at the moment something has gone wrong and you have less patience than usual.

That is why it is worth reading about them now, calmly, and not the first time you need them. You do not have to remember the syntax; it is enough to remember that the command exists.

And the most important of the five, if you keep only one: git reflog. What you think you lost is probably still there.

Comments