Split a commit into 2 commits with `git rebase`
Tags: git, pnpm, yarn, javascript
Published: 2022-12-05 18:31:40

---
title: Split a commit into 2 commits with `git rebase`
published: true
description: This post educates users how to split a single git commit into two separate commits using `git rebase`. This is useful when you are trying to isolate files which frequently have conflicts (like package lockfiles!). 
tags: git, pnpm, yarn, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rl8tbae1av8n1tylhy50.png
# Use a ratio of 100:42 for best results.
# published_at: 2022-12-05 18:04 +0000
---

## Overview
Git is a powerful version control system that allows developers to track and manage changes to their code. One of the key features of Git is the ability to use interactive rebasing to modify the history of a branch.

Interactive rebasing allows you to edit, reorder, and split commits in a branch. This can be useful when you need to clean up your branch history, or when you want to split a commit that contains changes for multiple files into separate commits.

## pnpm, yarn, npm lockfiles
Have you ever had to `git rebase` in your project but consistently had merge conflicts in your pnpm/yarn/npm lockfiles? You may have heard the advice to 'always commit your lockfile in an isolated commit'. 

This is because you can use the `drop` command in an interactive rebase to remove the commit so you can regenerate the lockfile after your rebase. 

Often times, I forget this and sometimes I end up with multiple files (including my lockfile) inside my single commit and now I cannot `drop` it. 

## Getting Started
In this tutorial, we will show you how to split a commit during an interactive git rebase. We will use a simple example to illustrate the steps involved in splitting a commit.

To begin, let's assume that you have a branch called `feature-branch` that is based on the `master` branch. The `feature-branch` contains three commits, `X`, `Y`, and `Z`, as shown below:

```bash
          A - B - C - D [master]
         /
    X - Y - Z [feature-branch]
```

The `Y` commit in the feature-branch contains changes for both `fileA` and `fileB`. However, you want to split this commit into two separate commits, one for `fileA` and one for `fileB`.

## Using `git rebase -i`

To do this, you need to start an interactive rebase using the `git rebase -i` command. In this example, we will use the master branch as the base branch, so the command would be `git rebase -i master`.

This will open an editor where you can specify the actions that you want to perform on each commit in the feature-branch. In this case, you want to split the `Y` commit, so you need to replace the `pick` command for commit `Y` with the `edit` command.

Once you save and close the editor, the rebase will start and it will stop at the `Y` commit. This will allow you to make changes to the `Y` commit.

## Split the Commit!

To split the `Y` commit, you first need to unstage the changes from the commit. This can be done using the `git reset HEAD~` command. This will leave the changes in your working directory, but they will not be staged.

Next, you can use the `git add` command to stage only the changes for `fileA`. Then, you can use the git commit command to create a new commit with the changes for `fileA`. This will create a new commit, `Z`, in the `feature-branch`, as shown below:

```bash
          A - B - C - D [master]
         /
    X - Y - Z [feature-branch]
```

Now, you can use the `git add` command to stage the remaining changes for `fileB`. Then, you can use the `git commit` command to create a new commit with the changes for `fileB`. This will create a new commit, `W`, in the `feature-branch`, as shown below:

```bash
          A - B - C - D [master]
         /
    X - Y - Z - W [feature-branch]
```

## Tada! 

Finally, you can use the `git rebase --continue` command to continue the interactive rebase. This will apply the changes that you made to the `Y` commit and create a new branch history with the two separate commits for `fileA` and `fileB` respectively!

Now anytime you have a pesky lockfile change included with other files in a commit, you can separate it out, and then `drop` them during your rebases to make interactive rebase efficient and clean!