Using interactive rebase in Git
Tags: repository, github, versioncontrol, git
Published: 2024-06-09 20:20:38

## About

An interactive rebase in Git is a process that allows you to edit a sequence of commits. This is typically used to clean up commit history before sharing changes with other members of the team.
## Case study

Let's study an example of making a clear 3-commit history out of the initial 5 commits. 

1. **Start an interactive rebase:** Start an interactive rebase for the last 5 commits. If your branch has 5 commits ahead of the base branch, you can use:

   ```
   git rebase -i HEAD~5
   ```

2. **Interactive rebase editor:** This command will open your default text editor with a list of the last 5 commits, starting from the oldest commit to the newest. The lines will look something like this:

   ```
   pick abc123 Commit message 1
   pick def456 Commit message 2
   pick ghi789 Commit message 3
   pick jkl012 Commit message 4
   pick mno345 Commit message 5
   ```

3. **Edit the commits:** Change the word "pick" to specify what you want to do with each commit. To squash commits into one, you can use the word "squash" or "s" for short. For example, if you want to combine commits 2, 3, and 4 into one, you would modify the list like this:

   ```
   pick abc123 Commit message 1
   pick def456 Commit message 2
   s ghi789 Commit message 3
   s jkl012 Commit message 4
   pick mno345 Commit message 5
   ```

4. **Save and close the editor:** After modifying the list, save and close the editor. Git will start the rebase process.

5. **Edit commit messages:** Git will then reopen the editor to allow you to combine commit messages. You can edit the commit messages to reflect the new commits. For example, you might see something like this:

   ```
   # This is a combination of 3 commits.
   # The first commit's message is:
   
   Commit message 2

   # This is the 2nd commit message:

   Commit message 3

   # This is the 3rd commit message:

   Commit message 4
   ```

   You can edit this to create a new combined commit message:

   ```
   Combined commit message for commits 2, 3, and 4
   ```

6. **Complete the rebase:** Save and close the editor. Git will complete the rebase process.

### Example

Assume your commits are:

1. `abc123` - Initial setup
2. `def456` - Added feature A
3. `ghi789` - Fixed bug in feature A
4. `jkl012` - Improved feature A
5. `mno345` - Added feature B

You want to have the following commits:

1. Initial setup
2. Feature A (including the fix and improvement)
3. Feature B

Your rebase edit list would look like this:

```
pick abc123 Initial setup
pick def456 Added feature A
s ghi789 Fixed bug in feature A
s jkl012 Improved feature A
pick mno345 Added feature B
```

And after saving the first list, you would combine the messages of the second, third, and fourth commits into something like:

```
Feature A (including the fix and improvement)
```

> The editor used for an interactive rebase in Git is determined by your Git configuration and environment settings. By default, Git uses the default editor configured for your system, such as `vi` or `nano` on many Unix-like systems, or Notepad on Windows.

By following these steps, you can adjust your commits into three sensible commits with the desired commit messages.

## Other commands for interactive rebase

During an interactive rebase in Git, several operations can be performed to modify the commit history. Here’s a short list of the key operations along with their syntax and explanations:

1. **pick** (or `p`):
   - **Syntax**: `pick <commit-hash> <commit-message>`
   - **Explanation**: Use the commit as-is. This is the default operation and is used to keep a commit unchanged.

2. **reword** (or `r`):
   - **Syntax**: `reword <commit-hash> <commit-message>`
   - **Explanation**: Use the commit, but modify the commit message.

3. **edit** (or `e`):
   - **Syntax**: `edit <commit-hash> <commit-message>`
   - **Explanation**: Pause the rebase to allow amendments to the commit. This can be used to change the content of the commit or the commit message.

4. **squash** (or `s`):
   - **Syntax**: `squash <commit-hash> <commit-message>`
   - **Explanation**: Combine the commit with the previous commit, merging their changes and allowing you to edit the commit message.

5. **fixup** (or `f`):
   - **Syntax**: `fixup <commit-hash> <commit-message>`
   - **Explanation**: Similar to `squash`, but discard the commit message of the commit being combined. The commit message of the previous commit is used.

6. **exec** (or `x`):
   - **Syntax**: `exec <command>`
   - **Explanation**: Execute a shell command. 

7. **drop** (or `d`):
   - **Syntax**: `drop <commit-hash> <commit-message>`
   - **Explanation**: Remove the commit entirely. This can be used to delete unnecessary or undesired commits from the history.

8. **break**:
   - **Syntax**: `break`
   - **Explanation**: Pause the rebase at this point to allow inspection or further manual intervention. This is useful for debugging the state of the repository.

And others.

### Usage example for some of the commands

Here's an example of what the rebase instructions file might look like when you initiate an interactive rebase:

```plaintext
pick a1b2c3d First commit message
reword b2c3d4e Second commit message
edit c3d4e5f Third commit message
squash d4e5f6g Fourth commit message
fixup e5f6g7h Fifth commit message
drop f6g7h8i Sixth commit message
```

Alternatively, use the first letters to for calling each of the commands:

```plaintext
p a1b2c3d First commit message
r b2c3d4e Second commit message
e c3d4e5f Third commit message
s d4e5f6g Fourth commit message
f e5f6g7h Fifth commit message
d f6g7h8i Sixth commit message
```
## References

1. [Git Tools - Rewriting History](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
2. [Vim Cheat Sheet](https://vimsheet.com/)