Tweaking commits with Git's Magic Time Machine✨, aka git rebase
Tags: git, productivity, magic, codequality
Published: 2020-09-10 00:04:58

> Magic is everywhere! Specially in your terminal, and our git has some of its own. In this post I'm going to show you a little of this *magic* that lives inside the `git rebase` command.
🐻 Bear in mind, this post assumes you are already familiar with git.

# git rebase

> 📖 Reapply commits on top of another base tip.

This sounds and looks just like `git merge`... right? 

```bash
git checkout feature
git rebase master
```

Not quite. `git rebase`, moves the branch and incorporates all of the new commits, **but *re-writing* the project history** by creating **brand new commits for each commit** in the original branch.

These brand new commits thingy thing, brings up the golden rule of rebase: **do not rebase on public branches**. 

Besides rewriting commits, we can add two other key features of `git rebase`:

- Doesn't make new commits (because it rewrites them)
- Can be used in the **same** branch we are working on

This three key features gives us the opportunity to tweak our commits, which comes really in handy when 

- we messed up with the commit message
- made a very tiny file change and its commit would be better off inside a larger one
- when we need to change the order of the commits
- remove a whole commit

## Getting our hands dirty

![Graph of a git branch with four commits](https://dev-to-uploads.s3.amazonaws.com/i/ip4k5i6u2ybnnp54xogr.png)

Let's say I've been working on this new feature branch, and 4 commits in, I want to make some changes to them using rebase. 

```bash
git rebase -i HEAD~4
```

- **git rebase**: calls, of course, the git-rebase command
- **-i:** Shorthand for *interactive,* this makes a list of the commits that we are about to rebase, letting us edit that list and how we are going to rebase them. This file is where we are going to do today's magic.
- **HEAD~4:** The tilde is used to point to a position relative to a specific commit, in this case, the HEAD; giving us its 4th parent.

Now, a file has been opened on your designed IDE called **git-rebase-todo** and we are ready to do some magic with out git project.

```bash
# git-rebase-todo
pick 4acdb1d First Commit of Feature
fixup be76710 Second Commit of Feature
drop 78acdd0 Third Commit of Feature
reword 9480b3d Fourth Commit of Feature
```

When we use `--interactive`/`-i` this file is going to tell git what to do with each of the commits listed. The list can be re-ordered and git will execute your orders from top to bottom! 

![Graph of a git branch with commits being reordered via git rebase](https://dev-to-uploads.s3.amazonaws.com/i/ipxtwyut0iehr2zx3vkc.png)

By default, all commits come with the option **pick**, but there are many options we can use to alter our commits. 
Let's see what that means and what we can do with the other commands rebase has for us.

### pick

**P**ick signals git to use the commit, this means, it will keep this commit and use it in its rebasing. 
➡ **When should I use pick?** Every time we want to keep a commit!

```bash
pick be76710 Super awesome commit message
# You can also use the short version: p
p be76710 Super awesome commit message
```

### reword

**Reword** signals git to use the commit just like **pick** but lets us change the commit message when it's about to be commited again. This option will prompt you with a file to edit with the previous commit message for you to edit.
➡ **When should I use reword?** Every time we want to keep a commit, but we need to make changes to it.

```bash
reword be76710 Super awesome commit message
# You can also use the short version: r
r be76710 Super awesome commit message
```

### edit

**E**dit signals git to use the commit, but stops just before commiting to let us make changes or adjustments. This amendments to the code are not limited at all. Everything will be included in the commit long as you stage them: this includes typos, a few more lines of code, or a whole new file.
➡ **When should I use edit?** Every time we want to keep a commit, but we need to slip in a few more changes to it.

```bash
edit be76710 Super awesome commit message
# You can also use the short version: e
e be76710 Super awesome commit message
```

### squash

**S**quash signals git to merge the commit with the previous one, this means, both commits will become one with a new hash. Git will let you reword the commit message of this newly created commit and will prompt you with a file to edit it.
➡ **When should I use squash?** Every time we want you want to meld one or more commits with a previous one.

```bash
squash be76710 Super awesome commit message
# You can also use the short version: s
s sbe76710 Super awesome commit message

```

### fixup

**F**ixup signals git to merge the commit with the previous one, just like **squash** but discarding the commit's message.
➡ **When should I use fixup?** Every time we wan to meld one or more commits with a previous one disregarding its message is.

```bash
pick 4acdb1d Super Awesome Commit
fixup be76710 This commit is going to be merged with the one on top of it
pick 9480b3d Another Super Awesome Commit
# You can also use the short version: f
f be76710 Super awesome commit message
```

![Graph of a git branch with a commit being merged with the previous one via git rebase and fixup](https://dev-to-uploads.s3.amazonaws.com/i/mdr2zv5yuly01q0ivgdi.png)

### drop

**D**rop signals git to remove the whole commit.
➡ **When should I use fixup?** Every time you want to discard all the changes made by a commit.

```bash
drop be76710 Super awesome commit message
# You can also use the short version: d
d be76710 Super awesome commit message
```

## So, again, how do I use this magic tricks?

**You've just commited a very big change to your new website index.html. Your eyes wonder upon the job done, and suddenly, a *nasty* typo appears out of nowhere.**

✨ Just make another commit with the fixed typo. Invoke the magic words on your terminal `git -i rebase HEAD~2` and then, use **fixup** to merge the commit done for the typo.

**After making three commits, you've noticed the first one has a commit message that others in your team would find confusing.**

✨ Just call upon the greatness of rebase with `git rebase -i HEAD~3` and use **reword** on the commit you'd like to change its message.

**You have noticed the whole commit you've done, five commits ago is wrong, but... there are many commits you don't want to lose using reset!**

✨ Rebase comes to hide all of those silly mistakes! Let's recite together on our terminal `git rebase -i HEAD~5` and using **drop** that commit is now gone forever!

## With great power comes great responsibility

Before using rebase, you have to make sure if at any point, the commits you are going to merge have already been merged to public branch, if that's the case... **don't us rebase.** Remember what we've learned about rebase making new commits? You'll have issues because we've just rewritten the commits history!
Another thing to keep in mind is, when we rebase, all the commits are applied one after the other, this means, dropping or changing the order of any commit might pop up conflicts you'll have to fix and then commit before rebase can continue. After you've successfully dealt with them, gracefully resume your rebase with `git rebase --continue`. Or just go with `git rebase --abort` and cry yourself to sleep remembering those conflicts... *oh lord... those conflicts.*

## 📚 Let's read more!

- By the way, I'm aware this post doesn't cover in depth the differences between `merge` and `rebase`, but I have good news **[🔗Atlassian has a great post about it](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)**.
- If you need a better way to visualize what `rebase` does to your branch, @lydiahallie has [**🔗 excellent animations** on how git works on this gorgeous post.](https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1#rebase)
- The options I've presented here are not the only ones `rebase` has. If this topic got you hooked, and you crave to expand your knowledge on them and rewriting history, [**🔗 git documentation on has a lot of good insight**](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).
- If you feel like getting a little more technical, @jessekphillips goes slightly [**🔗 more in depth with rebase**](https://dev.to/jessekphillips/interactively-rebase-with-git-4o7n) in a short but sweet post.

That's it from me for now, I hope you find it useful and on your next project less of these pesky typos plague your commit history, thanks to the magic of `rebase`✨