Search code examples
gittortoisegitvisual-studio-2022

How can I remove an old Git commit from master and turn it into its own branch?


There is a single commit C in my master branch history that we have decided needs more work. It is not the latest commit. There have been 10+ commits since then. Fortunately, none of the subsequent commits touched any of the files changed by C.

I want to remove this commit from the master branch and simultaneously create a new branch test-c from the changes in C. This way, more work can be done on it and then later on it can be merged into master.

So I want to go from this:

---A---B---C---D---E (master)

to this

---A---B---D---E (master)
                \
                 '---C (test-c)

or even just to this would be fine (I can merge later)

---A---B---D---E (master)
        \
         '---C (test-c)

The only relevant answer I could find on this makes it sound as if I need to either write a script or manually rebase each subsequent master commit (after C) on the previous one. I am dreading that. But that answer is 9 years old so I have hope there is a better way.

Is there an easier way to do this in Visual Studio 2022 (or Tortoise Git, which I also use)? I looked at what VS gave me when I right clicked on this commit in the master branch history. I see the following options

enter image description here

Is any of these what I want? Or must I do all that rebasing? If the latter is the case, I'd just as soon add a reverse-commit to master, then create a branch with the changes and let the history look cluttered)


Solution

  • You can revert the commit (leaving it in the history), create a new branch and then cherry-pick the original commit. Rewriting published history has a lot of problems, therefore I suggest to revert the changes of the commit.

    Cherry-picking is required because otherwise the reverted changes will not be merged again.

    1. git checkout master
    2. git revert bad-commit
    3. git checkout -b more-work
    4. git cherry-pick bad-commit
    5. Work on the new branch and eventually merge back

    If you really need to get rid of the original commit (removing it from the history, not just undoing its changes), you can use an (interactive) rebase. Interactive:

    1. git branch more-work bad-commit
    2. git rebase -i bad-commit^ master
    3. Change the line with bad commit from pick to drop (or delete it altogether`
    4. Save and exit the file

    Non-interactive:

    1. git branch more-work bad-commit
    2. git rebase --onto bad-commit^ bad-commit master