DEV Community

Cover image for 10 Git Commands You’ll Wish You Knew Earlier
Sylwia Laskowska
Sylwia Laskowska

Posted on

10 Git Commands You’ll Wish You Knew Earlier

Targeted at devs past the basics

Do you know Git? Of course you do! Today, I’ve got a few of my favorite Git commands for you. When I was a junior developer, my tech lead taught me most of them (hi Wojtek, if you’re reading this 👋) and later, I started teaching the same commands to my own junior and mid-level developers.

I’ve actually been meaning to write this article for months. But you know how it is. It’s evergreen content, it requires a bit of work, and meanwhile I kept coming up with other ideas, so I kept postponing it. What finally motivated me was @francistrdev, who recently published his own article about Git commands.

My article will be a little different, though. If you’re completely new to Git and still learning the basics, check out Francis’s Git Gud! article first. But if add, commit, pull, and push are already second nature to you, this article is for you.

These are, let’s say, intermediate-level commands. Useful ones. The kind you actually need at work, but not yet senior-level Git magic like:

Type three lines into your terminal and a spaceship will appear in your repository.

If you have other useful commands at this level, please share them in the comments!

BTW, if you feel like it, you can also follow me on Instagram! I’m planning to post what could grandly be called “dev lifestyle” content there. 😅 I have four conferences coming up this fall, for example, so expect some behind-the-scenes photos from my little tour around Europe. I only have a handful of followers there so far and absolutely no idea what this experiment will turn into, but here you go: @sylwia.lask

All right, let’s start.

1. & 2. git merge vs git rebase

Haha, first point and we already have two commands.  The reason I’m putting them together is that a lot of developers, even experienced ones, treat merge and rebase almost interchangeably.

And sure, their high-level purpose is similar: you want to integrate the history of one branch into another. Very often that means updating your feature branch with changes from main, develop, or another feature branch.

But the way they do it is quite different. Imagine you have this:

A---B---C main
     \
      D---E feature
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You’ve been happily working on your feature branch, while someone else added commit C to main. Now you want to bring those changes into your branch.

Merge

If you run:

git merge main
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

while you’re on feature, Git combines both histories. You usually end up with something like this:

A---B---C------M
     \        /
      D---E---
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

M is a merge commit.

The original history stays intact. Git remembers that your feature branch diverged from main, both branches evolved independently for a while, and then they were joined together.

This can be a good thing because it preserves the real history of what happened. The downside is that if you merge main into your feature branch over and over again, your history can eventually start looking like spaghetti.

Rebase

Now let’s say instead you run:

git rebase main
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git takes commits D and E, temporarily removes them, moves your branch onto the latest main, and then reapplies your commits on top.

You get:

A---B---C---D'---E'
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Much cleaner.

But notice the apostrophes. D' and E' are not technically the same commits as D and E. Git created new commits with new hashes. That means rebase rewrites history.

This is why a very useful rule of thumb is:

Rebase your own work. Be careful rebasing shared history.

If you’re working alone on a feature branch, rebasing it is usually perfectly fine. If three other developers have already based their work on your commits, rebasing those commits can make everyone’s life considerably more exciting. And not in a good way.

And what about conflicts?

Both merge and rebase can result in conflicts. 

With a merge, Git tries to combine the two histories in one operation. You resolve the conflicting files, stage them:

git add .
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

and then continue:

git merge --continue
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

With rebase, things can be slightly more annoying because Git reapplies your commits one by one.

This means you may resolve a conflict, continue the rebase...

git add .
git rebase --continue
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

...and then get another conflict in the next commit. And another one. And another one. At which point you start questioning every career decision that led you here. 😅

But there’s also a small bonus. If you completely mess things up and just want to stop the entire circus, you can do:

git merge --abort
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

or:

git rebase --abort
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git will try to return you to the state from before the merge or rebase started. Extremely useful feature. 😁


3. git commit --amend

This is one of those commands I learned to love very quickly as a junior. Imagine you’ve just created a beautiful, perfectly round little commit. Then you look at the code and notice you forgot something.In my case, it was usually:

console.log("WTF");
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You now have two options. Option one: make another glorious commit:

Remove console log
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Which, let’s be honest, is not exactly the pinnacle of Git history aesthetics.

Or you can simply add the forgotten change to the previous commit. For example:

git add forgotten-file.ts
git commit --amend --no-edit
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

--no-edit means:

Add these changes to the previous commit, but keep the existing commit message.

If you want to change the commit message as well, just run:

git commit --amend
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git will open your configured editor and let you modify it.

There is one important detail here. amend doesn’t literally edit the existing commit. It creates a new commit containing the updated contents. And because commit hashes depend on the contents and metadata of the commit, the hash changes.

If you’re working locally and haven’t pushed the branch anywhere yet, no problem. But if the branch already exists on remote, your local history no longer matches the remote history. So when you try:

git push
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

you’ll probably get something like:

rejected (non-fast-forward)
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Now, if you are absolutely sure nobody else is working on that branch, you could technically do:

git push --force
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

But what if you’re not sure?

And this brings us very smoothly to the next point.


4. git push --force-with-lease

After a rebase, amend, interactive rebase, squash, or anything else that rewrites your commits, your local branch history may no longer match the version stored on remote.

You can solve that with:

git push --force
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

But --force is basically saying:

My local version is the truth. Replace whatever is on remote with this.

If someone pushed something to that branch in the meantime, you can overwrite their work. They may get angry.  And rightly so. 😏

A much safer option is:

git push --force-with-lease
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

In simplified terms, this tells Git:

Force-push my version, but only if the remote branch still looks the way I expect it to.

If the remote branch changed since the state your local Git knows about, for example because someone else pushed new commits, Git refuses the push instead of blindly overwriting them.

So instead of destroying someone’s afternoon, you get an error. I generally recommend:

--force-with-lease
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

over:

--force
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

whenever possible.


5. git rebase -i

For me, this is a very important command. Almost the king of Git. xDDDD Interactive rebase lets you do almost anything you want with your recent commits.

In other words, you can commit every single line individually, change everything ten times, create commits like:

Add validation
Fix validation
Actually fix validation
Fix validation again
Remove console.log
Please work now
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

and then later turn the whole mess into an elegant Git history.

Let’s say you want to edit your last five commits. You run:

git rebase -i HEAD~5
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git opens your configured editor — Vim, Nano, VS Code, or whatever you use — and shows something similar to:

pick a111111 Add login form
pick b222222 Add validation
pick c333333 Fix typo
pick d444444 Fix validation
pick e555555 Remove debug log
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Now comes the fun part. You can replace pick with different commands.

pick

Keep the commit exactly as it is.

pick a111111 Add login form
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

reword

Keep the commit contents, but change its message.

reword a111111 Add beautiful login form
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

edit

Pause the rebase at that commit and let you modify it. Useful if you want to change the actual contents of an older commit.

squash

Combine the commit with the one before it.

For example:

pick   a111111 Add login form
squash b222222 Add validation
squash c333333 Fix validation
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git turns those commits into one and lets you edit the final commit message.

So instead of:

Add login form
Add validation
Fix validation
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

you can end up with:

Add login form with validation
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Beautiful. Round. Perfect.

fixup

fixup is similar to squash, but it throws away the commit message of the fixup commit.

For example:

pick  a111111 Add login form
fixup b222222 Fix typo
fixup c333333 Remove console.log
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You probably don’t care about preserving the historical significance of:

Remove console.log
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

So fixup is perfect here.

drop

Remove the commit completely.

drop c333333 Terrible idea
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Goodbye.

Of course, there are different schools of thought about how much you should clean up your commits. Some senior developers say that submitting a nicely cleaned-up commit history for review is simply good manners. Others do not care in the slightest and think it’s unnecessary because GitHub, GitLab, or whatever platform you use can simply squash everything when merging the PR anyway.

But!!! What if you don’t want to click Squash and merge? What if your feature logically contains two commits and you actually want to preserve both? That happens.

So whether you use interactive rebase once a week or once every six months, I still think it’s worth knowing the king:

git rebase -i
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

6. git stash

This one comes in handy very often. You start working on a nice little feature. Or, these days, Kiro or Claude Code is working very hard while you watch.  Suddenly someone reports a production bug.

Unfortunately, you now have to temporarily abandon your beautiful feature and switch to something else. The problem is that your current work is completely unfinished. You have debug logs everywhere, half the files are modified, the project doesn’t even build, and you definitely don’t want to commit this mess.

Although, of course, now you know about amend, so you could eventually clean it up.

But there’s a better solution:

git stash
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git temporarily stores your uncommitted changes and returns your working directory to a clean state.

Now you can switch branches:

git switch main
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

fix your production disaster, and later come back.

One important detail: by default, git stash stashes tracked files, but not new untracked files. If you also want to include newly created files, use:

git stash -u
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

or, even better, give your stash a useful name:

git stash push -u -m "WIP login feature"
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Because once you have several stashes named basically “WIP”, future you will hate present you.

git stash list

To see all your stashes:

git stash list
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You might get:

stash@{0}: On feature/login: WIP login feature
stash@{1}: On feature/cart: experiment
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

git stash show

To see what a particular stash contains:

git stash show stash@{0}
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

And if you want the full diff:

git stash show -p stash@{0}
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

git stash apply

To restore a stash:

git stash apply stash@{0}
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

The changes are restored, but the stash remains in the list.

git stash pop

You can also use:

git stash pop
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

This applies the stash and, if successful, removes it from the stash list.

So, roughly:

apply = restore
pop   = restore + remove from stash
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Very simple, very useful.


7. git cherry-pick

I have to admit this is one of the intermediate Git commands I use most often. Imagine there’s one specific commit on another branch that you want in your current branch.

You don’t want to merge the whole branch. You don’t want to rebase onto it. You literally need one thing. For example, in my project recently, I needed a commit containing configuration for newly created environments. Perfect use case.

You simply run:

git cherry-pick <commit-hash>
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

For example:

git cherry-pick a1b2c3d
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git takes the changes introduced by that commit and applies them to your current branch.

Important detail: it creates a new commit. So the resulting commit contains essentially the same changes, but it gets a new hash. Imagine this history:

main
A---B---C

feature
     \
      D---E---F
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You’re on main, but you only want E.

After:

git cherry-pick E
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

you get something like:

A---B---C---E'
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Simple.

But I’ll admit that, being a lazy creature, I use cherry-pick in slightly less noble ways too. Sometimes something gets completely messed up on my branch. The rebase goes badly, the history looks suspicious, conflicts start multiplying, and after a while I decide: I'll create a completely new branch from the correct place at the top of the tree. 😅

And because — thanks to the previous commands ☺️ — my commits are already nice and round, I simply cherry-pick them one by one onto the new branch.

I’m sure some Git pro is currently shaking their head at me, but let me put it this way: It works for me. 😀


8. git reset --soft, --mixed, --hard

Three ways of moving back in history, each with a different answer to the question:

What should happen to my changes?

Because how many times do we start working on something, write some code, and then realize: Nope. This whole idea was bad. Let’s go back.

The easiest way to understand reset is to think about three layers:

Commit history
Staging area
Working directory
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Now we have three increasingly dramatic levels of reset. And every next one has greater potential to cause a small heart attack if you use the wrong one.

git reset --soft

Let’s say you want to undo the last commit:

git reset --soft HEAD~1
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git moves HEAD back by one commit, but all the changes from the removed commit remain staged.

So if your history was:

A---B
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

after the reset, your branch points to:

A
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

but the changes introduced by B are still ready to commit.

This is useful when you committed too early and want to recreate the commit differently.

git reset --mixed

Now:

git reset --mixed HEAD~1
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

or simply:

git reset HEAD~1
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

because --mixed is the default.

Again, Git moves back one commit.

But this time the changes are left in your working directory unstaged.

So nothing disappears from your files, but you need to git add things again before committing.

git reset --hard

And now we enter the danger zone:

git reset --hard HEAD~1
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

This moves HEAD back and updates both the staging area and working directory to match that commit. In other words, the changes disappear from your files too.

So:

--soft  → keep changes staged
--mixed → keep changes unstaged
--hard  → discard changes from the working tree
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Use the last one with some awareness of what you’re doing. But what if you go one step too far and accidentally delete something you absolutely did not mean to delete?

And that brings us to...


9. git reflog

A command I use very rarely. But oh, how many times it has saved my ass.

For example, when I once ran git reset --hard and instead of removing my last changes, I basically removed the branch I had been working on for two days. 😀Amazing experience. Highly recommended.

The important thing to understand is that git log shows you commits reachable from the history you’re currently looking at. If you reset your branch backwards, some commits may disappear from git log.

That does not necessarily mean Git has immediately deleted them. Git also keeps a local log of movements of references such as HEAD. You can inspect that with:

git reflog
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You may see something like:

e35fa12 HEAD@{0}: reset: moving to HEAD~2
821cd77 HEAD@{1}: commit: Add authentication
f992ab1 HEAD@{2}: commit: Add login page
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Aha! There’s your missing commit.

Now you have several options. You could move the branch back to it:

git reset --hard 821cd77
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

But personally, if I’m already in panic-recovery mode, I prefer doing something safer first:

git branch rescue 821cd77
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Now the commit is reachable from a branch again and I can calmly inspect what happened without immediately rewriting anything else.

The key difference is:

git log
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

shows your visible commit history.

git reflog
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

shows where your local references, especially HEAD , have pointed recently.

There is one important limitation, though. Reflog is not a magical backup of every character you’ve ever typed. If your changes were never committed, stashed, or otherwise stored as Git objects, reflog cannot magically resurrect them.

So yes, if you worked for six hours without committing anything and then destroyed those changes... Well. Maybe this will teach you to commit more often next time.


10. git revert

And finally:

git revert
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Imagine you release a commit to production.  Or, in the slightly less hardcore version of this scenario, to some shared develop branch.

Something goes very wrong. Everything breaks. So what now? Do you run:

git reset --hard
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

on the production branch?

Do you start performing an exorcism?

Fortunately, no. The elegant way to undo a commit while preserving a clear record of what happened in your repository history is:

git revert <commit-hash>
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Imagine your history looks like this:

A---B---C
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

and C introduced the disaster.

You run:

git revert C
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

Git does not remove C.

Instead, it creates a new commit that applies the opposite changes:

A---B---C---D
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

You may end up with something like:

C: Add new payment logic
D: Revert "Add new payment logic"
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

This is extremely useful on shared branches because you are not rewriting public history. Everyone can clearly see:

  1. the original change happened,
  2. it caused trouble,
  3. it was reverted.

Compare that with resetting the branch and force-pushing it backwards, which rewrites history and can cause problems for everyone else working on it.

So, as a general rule:

Shared branch + bad commit → revert
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

is usually much safer than:

reset + force push
⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 ⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026

And that’s it!

As I said at the beginning, if you use other intermediate Git commands that regularly save you time or save your ass, please share them in the comments. Usually the comments under my articles end up being much better than the article itself, which continues to make me very happy.

Also, please note that last week’s article was a list. This week’s article is a list. And — spoiler alert — next week’s article will also be a list!

This is not because I smelled clicks and decided to turn into BuzzFeed. It just somehow happened that way. 😅

I hope you learned something new. And if you didn’t, I hope it was at least fun to read. 😁

Top comments (96)

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
francistrdev profile image
FrancisTRᴅᴇᴠ (っ◔◡◔)っ

Thanks for the mention and great detail on using Git :D

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Haha never enough of Git 🙂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
freshcaffeine profile image
Andy Robinson

Im looking forward to the followup about git work-trees. With agentic now the mainstay, work-trees are becoming increasingly more invaluable

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Haha, don’t tempt me! 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
pengeszikra profile image
Peter Vivo

A best how to use git short document!

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Ooooh, thank you so much! ☺️ Now I can just send this article to juniors instead of explaining all of this on a call every time. 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
anchildress1 profile image
Ashley Childress

This is exactly how I started writing! So I didn't have to explain myself multiple times. 😂 Great article!

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Thank you so much! 😄 Haha, I also wrote a few articles specifically for my juniors. But then somehow this whole writing thing took a rather unexpected turn. 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
anchildress1 profile image
Ashley Childress

Sounds like we did much of the same thing!! It is a lot of fun. 🤩

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
pengeszikra profile image
Peter Vivo

Thats why is working so well

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Hahahaha, should've written this a few years ago! 😅

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
nyaomaru profile image
nyaomaru

Git commands are basic, but really important for every developer.
I think this will be a valuable article for many people! 😸

I use aliases in my .zshrc, for example, gc="git commit -S".

It makes my daily Git workflow a little bit faster.
Do you have any similar tricks or customizations in your setup? I'm curious! 😸

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Haha, you know what? I actually don’t! 😄 I know about Git aliases, but I prefer typing the commands manually so I don’t forget them, partly because then I can recite them from memory when explaining Git to juniors. 😂

But we do have a very funny Polish repo with Git aliases called “git kurwa” (“kurwa” is a Polish swear word 😅). So apparently we’ve found a very Polish solution to Git frustration. 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
nyaomaru profile image
nyaomaru

Actually, I don’t remember all the Git commands either. 😹
I only make aliases for the ones I use all the time.

And I had no idea git kurwa existed! Thanks for introducing me!
github.com/jakubnabrdalik/gitkurwa

"Git, kurwa!" 😹

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Hahaha, yes! 😂 It was super popular in Poland some time ago. I think pretty much every Polish developer had come across “Git, kurwa!” at some point.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
buildbasekit profile image
buildbasekit

Hi Sylwia! 😂

git reflog is basically Git’s emergency contact. You hope you never need it, but the moment you accidentally nuke two days of work, suddenly it’s your best friend.

Now I’m curious: which Git command has saved you from the biggest disaster so far? 😄

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Haha, that’s a good question! 😄 I’d say git revert has definitely saved me from the biggest disasters. git reflog can save your work, sure, but git revert can save production. 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
pascal_cescato_692b7a8a20 profile image
Pascal CESCATO

Your article deserves to be shared with anyone who uses Git… and should be declared a public service. I can't even begin to tell you how many mistakes I would have avoided if you'd had me read it when I first started using Git!

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Thank you so much, Pascal! Coming from you, that’s truly an honor! 😊

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
kenwalger profile image
Ken W Alger

git reflog has rescued me from more than one moment of "well, that was unfortunate." 😂

But your git revert section jumped out at me for a completely different reason. I've been writing a lot lately about durable AI memory and decision history, and Git keeps turning out to be a surprisingly good mental model.

A revert doesn't pretend the original commit never happened. It preserves the original event and adds a new event saying, effectively, "this no longer governs the current state." That's very close to the distinction I've been working through between correction, supersession, and invalidation in AI memory.

Current state alone says what exists now. History tells you how it became that way.

Apparently the answer to half of my AI architecture questions continues to be: we solved a version of this problem decades ago with Git. 😄

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Oh wow, that’s actually such a great observation! And yes, the more I work with AI agents, the more I feel like we keep rediscovering problems from good old software engineering. 😂

What makes it even more interesting is that in traditional software development, we’ve already solved many versions of these problems over the years. With agents, we’re suddenly looking at them from a new angle and still have so much room to figure out how those old lessons translate.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
adamthedeveloper profile image
Adam - The Developer ✨

Alot of the ones that we rarely use are always the ones that end up saving our assess all the time. you think reflog might be useless? nah it just means you haven't screwed up enough lmao

when i started learning version control, i didnt think there was ever a UI and my default has always been through the CLI and i've always thought it was the default way to do version control for every developer... for large, complex changes, i rely on the Gitlens extensions.

until last year, i had a new member joining my team and he was using this blue UI thing i forgot the name of, i asked him what it was and he said it's just git commands with UI and i was like whatttt, they have that? lmao but hey, it gets the job done!

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Hahaha, I wonder if that blue UI thing was SourceTree? 😄 I absolutely love SourceTree and I’m kind of addicted to it. 😂

To be clear, I run probably 99% of my Git commands from the CLI (although I’ll occasionally create a local branch from the GUI when I’m feeling lazy 😅). But I’m a very visual person, and SourceTree draws the branch and commit tree so beautifully that I can immediately see what’s going on in the project.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
adamthedeveloper profile image
Adam - The Developer ✨

Yes!!! it was SourceTree!!! I've also thought about trying it out but then again, maybe I'm just lazy but I'm just not ready to try any new GUI for anything at the moment haha

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Haha, I think if you don’t feel like you need it, there’s really no reason to force yourself to try it. 😄

Funny enough, SourceTree was actually introduced to me by a backend developer who also did pretty much everything from the CLI. He just liked having a visual representation of the branch tree too. 😂 So apparently there’s a whole secret society of “CLI for commands, GUI for looking at pretty trees” developers.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
georgekobaidze profile image
Giorgi Kobaidze

Great list! Though I can’t imagine git merge, rebase, or even stash being unknown to any developer on God's green earth. Those are basically the bread and butter of Git.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Thanks! And that’s actually a very fair objection, one I’m happy to defend, because I do have a reason for each of those. 😄

First, junior developers often know merge, but either haven’t heard much about rebase, or they’ve heard of it without really understanding how it works or how it differs from merging. That’s exactly why I devoted quite a bit of space to explaining the difference.

Funny enough, recently even a senior developer on my team casually referred to “rebasing the branch,” and I was like, “But… we merged it there, didn’t we?”. Which actually mattered quite a lot in that particular situation. His answer was basically, “Yeah, I was just using it as shorthand.” I hope he wasn’t bluffing. 😂 But either way, imagine the confusion that kind of wording can create for juniors!

As for stash, I also really hope everyone knows the basic command. 😄 That section was more about going beyond plain git stash and showing things like stash list, apply, and pop.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
gamya_m profile image
Gamya

The merge vs rebase section is the one that finally made things click for me, I'd been using both without really understanding why I was choosing one over the other. The diagram of commits being replayed with new hashes is such a cleaner way to explain why rebasing shared history is risky.

git stash is probably the one I reach for most often in my day to day, that moment where you're halfway through something and a bug report lands and you just need to put everything down cleanly without committing a mess.

One I'd add at this level: git log --oneline --graph --all — not a command that does anything dramatic, but seeing the branch structure visually in the terminal helped me understand what merge and rebase were actually doing to my history way faster than any explanation did.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Thanks so much for the comment! 😄 And yes, --graph is great!

I have to admit that even though I type probably 90% of my Git commands manually, I still like using SourceTree, pretty much exclusively to look at the branch and commit tree. 😂 I’m definitely a visual learner, so being able to actually see the history makes everything much easier for me.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
glenallen profile image
Glen Allen

git reflog deserves more attention than it usually gets. Most Git commands are about changing the state of your repository, while reflog gives you a way to understand how you got there when something goes wrong. That makes it less of a daily workflow command and more of a recovery tool—and probably one of the best safety nets to learn before you actually need it.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
artyomsv profile image
Artjoms Stukans

Good framing, but worth to remember reflog lives inside .git, so it saves you only from yourself. When my SSD died the reflog died in same second, and what actually brought the thing back was a 13MB snapshot sitting on another machine. Local safety net and off machine copy are two different things, and most people have only first one.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

That’s a very good point, thanks for the clarification! Of course, there are plenty of situations where reflog won’t save you: reflog entries expire (typically after 90 days for reachable entries, as I remember), the repository itself might be corrupted or lost, or the changes simply might never have been committed in the first place.

There are lots of nuances here, but if the repo is still alive and you’ve accidentally nuked something, it’s always worth trying your luck with git reflog. 😄

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
artyomsv profile image
Artjoms Stukans

Yes, and expiry has funny detail in it. The 90 days is for reachable entries, unreachable ones go after 30 by default, and unreachable is exactly what you come to reflog for. So real window is shorter than people think, and it runs quietly while you postpone looking.

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026 Thread
 
sylwia-lask profile image
Sylwia Laskowska

Exactly! Although my coworkers and I always joked that you usually have more than enough time anyway, because most of the time you reach for reflog about a minute after realizing you’ve just deleted your own work. 😂

⚡ Match Highlights: sylwia lask/ git commands youll wish you knew earlier fcp - Info Live Streaming 2026
 
sylwia-lask profile image
Sylwia Laskowska

Exactly! Especially when you accidentally click the wrong thing somewhere, or when a rebase goes very, very wrong. 😂 That’s when git reflog suddenly becomes your best friend.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.