Skip to content

Commit

Permalink
Storify fixup and interactive rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
Chalarangelo committed May 1, 2024
1 parent fbba06d commit 639aa0c
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 18 deletions.
1 change: 1 addition & 0 deletions .vscode/spellright.dict
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ pathspec
unstaged
fileglob
fixup
autosquashed
48 changes: 40 additions & 8 deletions content/snippets/git/s/create-fixup-commit.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,56 @@
---
title: Create a fixup commit
type: snippet
title: Create a fixup commit in Git
shortTitle: Create fixup commit
type: story
language: git
tags: [commit]
cover: tools
dateModified: 2021-04-13
excerpt: If you find yourself needing to fix a previous commit, you can create a fixup commit that can be autosquashed in the next rebase.
dateModified: 2024-05-02
---

Creates a fixup commit that can be autosquashed in the next rebase.
If you find yourself needing to **fix a previous commit**, you can create a **fixup commit** that can be autosquashed in the next rebase. This allows you to keep your commit history clean and organized.

- Use `git commit --fixup <commit>` to create a fixup commit for the specified `<commit>`.
- After running `git rebase --autosquash`, fixup commits will be automatically squashed into the commits they reference.
## Creating a fixup commit

Simply use `git commit --fixup <commit>` to create a fixup commit for the specified `<commit>`. After running `git rebase --autosquash`, fixup commits will be automatically squashed into the commits they reference.

> [!NOTE]
>
> You can learn more about Git's **interactive rebase** in the [relevant article](/git/s/interactive-rebase).
```shell
git commit --fixup <commit>
# Syntax: git commit --fixup <commit>

# Examples
git add .
git commit --fixup 3050fc0de
# Created a fixup commit for `3050fc0de`
git rebase HEAD~5 --autosquash
# Now the fixup commit has been squashed
```

## Alias for creating fixup commits

As creating a fixup commit might be a very common operation, it's easy to create an **alias** for it. You can use `git config` to create an alias for creating fixup commits.

```shell
git config --global alias.fix 'commit --fixup'
# Now you can use `git fix <commit>` to create a fixup commit

git add .
git fix 3050fc0de
# Created a fixup commit for `3050fc0de`
```

## Simplifying fixup commit creation

Finding the commit hash to reference (e.g. using `tig`) can be cumbersome. Luckily, you can install `fzf` and add an alias that uses it to **select the commit hash interactively**. Then, you can use it to see the commit list and select the one you want to fix.

```shell
# Make sure `fzf` is installed (e.g. `brew install fzf` on MacOS)
git config --global alias.fixup '!git log -n 50 --pretty=format:"%h %s" --no-merges | fzf | cut -c -7 | xargs -o git commit --fixup'

git fixup
# Opens a list of the last 50 commits to choose from
# After selecting a commit, a fixup commit is created
```
55 changes: 45 additions & 10 deletions content/snippets/git/s/interactive-rebase.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,62 @@
---
title: Perform an interactive rebase
type: snippet
title: Perform an interactive rebase in Git
shortTitle: Interactive rebase
type: story
language: git
tags: [branch]
cover: tea-laptop-table
dateModified: 2021-04-13
excerpt: Reorder, squash, and edit commits interactively using Git's interactive rebase feature.
dateModified: 2024-05-02
---

Performs an interactive rebase.
If you want to **rewrite the commit history of a branch**, Git provides an **interactive rebase** feature that allows you to reorder, squash, and edit commits interactively. This can be useful for cleaning up your commit history before merging a branch or for combining multiple commits into a single one.

- Use `git rebase -i <commit>` to perform an interactive rebase.
- You can edit the rebase file to change the order of the commits and the action to perform for each one (pick, squash, drop, reword etc.).
- You can optionally use the `--autosquash` option to automatically squash fixup commits.
- If you have merge conflicts or stop to make changes, you can continue the rebase when ready using `git rebase --continue` or abort it using `git rebase --abort`.
Simply using `git rebase -i <commit>` will **open an editor** with a list of commits and actions to perform for each one. You can reorder the commits, squash them together, edit commit messages, and more.

> [!TIP]
>
> If you want to learn how to [configure Git's default text editor](/git/s/configure-default-text-editor) before using this command, check the linked article.
If you encounter **merge conflicts** or need to stop the rebase to make changes, you can continue the rebase when ready using `git rebase --continue` or abort it using `git rebase --abort`.

Additionally, you can use the `--autosquash` option to **automatically squash fixup commits** into the commits they are fixing.

> [!NOTE]
>
> You can read more about **fixup commits** in the [relevant article](/git/s/create-fixup-commit).
```shell
git rebase -i [--autosquash] <commit>
# Syntax: git rebase -i [--autosquash] <commit>

# Examples
git rebase -i 3050fc0de
# Performs an interactive rebase starting from `3050fc0de`

git rebase -i --autosquash HEAD~5
# Performs an interactive rebase of the last 5 commits,
# automatically squashing fixup commits
```

The options that are available to you during an interactive rebase are multiple, but the ones that are **most often used** are the following:

- `p`, `pick`: Use the commit as is.
- `r`, `reword`: Use the commit, but edit the commit message.
- `e`, `edit`: Use the commit, but stop for amending.
- `s`, `squash`: Combine the commit with the previous one.
- `d`, `drop`: Remove the commit.
- `f`, `fixup`: Like `squash`, but discard the commit message.
- `x`, `exec`: Run a shell command.
- `b`, `break`: Stop for amending. Continue with `git rebase --continue`.

You can either use the **full command** or the **shorthand** version when specifying the action for each commit. Below is an example of a commit list in an interactive rebase:

```shell
p c191f90c7 Initial commit # Keep this commit
pick 3050fc0de Fix network bug # Keep this commit
r 7b1e3f2a2 Update README # Edit the commit message
d 3e4f5d6a7 Commit sensitive data # Remove this commit
edit 9a8b7c6d5 Add new feature # Stop for amending
pick 1a2b3c4d5 Fix bug # Keep this commit
f 6d5c4b3a2 Add new feature # Squash this fixup commit
pick 5a6b7c8d9 Update README # Keep this commit
s 4b3c2d1a0 Update README # Squash this commit
```

0 comments on commit 639aa0c

Please sign in to comment.