GLM 4.5 Air

How to Move Git Commits to New Branch: Complete Guide

Learn how to move recent Git commits from master to a new branch and reset master with this complete guide. Includes step-by-step commands and troubleshooting tips for clean Git workflows.

Question

How do I move recent commits from the master branch to a new branch and reset master to before those commits were made? For example, I want to transform this state:

master A - B - C - D - E

Into this state:

newbranch     C - D - E
             /
master A - B 

What Git commands should I use to accomplish this workflow?

GLM 4.5 Air

Brief Answer

To move recent commits from master to a new branch and reset master, first create a new branch from the current commit using git branch newbranch, then reset master to the previous commit with git reset --hard HEAD~1 (for one commit) or git reset --hard <commit-hash> for a specific commit. This will effectively move commits C, D, and E to the new branch while leaving master at commit B.

Contents

Understanding the Git Workflow

Before diving into the commands, it’s essential to understand what you’re trying to accomplish. In Git, branches are simply pointers to specific commits. When you want to “move” commits from one branch to another, you’re actually creating a new pointer and adjusting the existing pointer.

In your example:

master A - B - C - D - E

You want to:

  1. Create a new branch that points to commit E
  2. Move the master branch pointer back to commit B

The result will look like:

newbranch     C - D - E
             /
master A - B 

This is a common workflow when you’ve made some commits on master that you realize should have been on a feature branch, or when you want to isolate recent work for separate review or deployment.

Step-by-Step Implementation

Here’s the exact sequence of commands to accomplish your goal:

1. Create the New Branch

First, create a new branch from your current HEAD (which is at commit E):

bash
git branch newbranch

This creates a new branch pointer named “newbranch” that points to the same commit as your current HEAD (commit E).

2. Reset the Master Branch

Now, reset the master branch to the desired previous commit. You have several options depending on your exact needs:

Option A: Reset by number of commits

If you know exactly how many commits you want to remove (in this case, 3 commits: C, D, and E), you can use:

bash
git checkout master
git reset --hard HEAD~3

The HEAD~3 syntax refers to the commit that is three parents back from your current HEAD.

Option B: Reset by commit hash

If you know the exact hash of commit B, you can reset to that specific commit:

bash
git checkout master
git reset --hard <commit-hash-of-B>

You can find the commit hash using git log --oneline or git log.

Option C: Interactive Reset

If you’re not sure exactly how many commits to remove or want to be more selective:

bash
git checkout master
git reset --soft HEAD~3

The --soft option keeps your changes staged but doesn’t remove them from the working directory, allowing you to selectively commit them.

3. Verify Your Branches

After running these commands, verify the state of your branches:

bash
git log --oneline --graph --all

This should show you the branch structure you wanted:

* E (newbranch)
* D
* C
|
* B (master)
* A

Or if you used the hash method:

* E (newbranch)
* D
* C
|
* B (master)
* A

Alternative Reset Approaches

Using git checkout and git reset

An alternative approach is to create and switch to the new branch in one step:

bash
git checkout -b newbranch
git checkout master
git reset --hard HEAD~3

This sequence achieves the same result but with slightly different commands.

Using git cherry-pick

If you only want to move specific commits rather than all recent commits, you could use git cherry-pick:

bash
git checkout -b newbranch
git checkout master
git reset --hard HEAD~3
git cherry-pick C..E

This would only move the specific commits you want to preserve.

Verifying Your Branches

After performing these operations, it’s crucial to verify that your branches are in the expected state:

bash
# Show commit history with branch pointers
git log --oneline --graph --decorate --all

# Show the current branch
git branch -v

# Show the last commit on each branch
git for-each-ref --format='%(refname:short) %(objectname:short) %(contents:subject)' refs/heads/

These commands will help you confirm that:

  1. The newbranch points to the latest commit (E)
  2. The master branch now points to commit B
  3. The commits C, D, and E are no longer part of the master branch history

Potential Pitfalls and Solutions

1. Losing Commits Forever

Problem: If you use git reset --hard and haven’t pushed your commits yet, those commits will be permanently removed from your local repository’s master branch.

Solution: Always make sure you’ve either:

  • Created the new branch first
  • Or have a backup of your work in another repository

2. Already Pushed Commits

Problem: If you’ve already pushed commits C, D, and E to a remote repository, resetting master will create a divergence between your local and remote history.

Solution: After resetting locally, you’ll need to force push to update the remote branch:

bash
git push origin master --force

Warning: Force pushing can overwrite other people’s work if they’ve based work on the commits you’re removing.

3. Uncommitted Changes

Problem: If you have uncommitted changes in your working directory, git reset --hard will discard them.

Solution: Either commit your changes first or stash them:

bash
git stash
# After reset
git stash pop

When to Use This Workflow

This type of branch manipulation is useful in several scenarios:

  1. Isolating Feature Work: When you’ve accidentally committed feature work directly to master and want to move it to a proper feature branch.

  2. Creating Release Branches: When you want to create a release branch from a specific point while continuing development on master.

  3. Experimentation: When you want to isolate recent experimental work that might not be ready for the main branch.

  4. Code Review: When you want to separate commits for different reviewers or review phases.

  5. Hotfix Isolation: When you need to quickly create a hotfix branch while preserving the current state of master.

Conclusion

Moving recent commits from master to a new branch and resetting master is a common and useful Git workflow. The key commands are:

  1. git branch newbranch to create the new branch
  2. git checkout master to switch back to master
  3. git reset --hard HEAD~N (where N is the number of commits to remove) to reset master

Remember to:

  • Always verify your branch structure after making changes
  • Be cautious with --hard resets as they can permanently discard changes
  • Consider the impact on team members if working in a shared repository
  • Use --soft or --mixed resets if you want to preserve changes in a different way

This workflow gives you precise control over your Git history and helps maintain clean, organized branching structures in your repositories.