Break a previous commit into multiple commits

前端 未结 14 2058
渐次进展
渐次进展 2020-12-20 13:09

Without creating a branch and doing a bunch of funky work on a new branch, is it possible to break a single commit into a few different commits after it\'s been committed to

相关标签:
14条回答
  • 2020-12-20 13:33

    Please note there's also git reset --soft HEAD^. It's similar to git reset (which defaults to --mixed) but it retains the index contents. So that if you've added/removed files, you have them in the index already.

    Turns out to be very useful in case of giant commits.

    0 讨论(0)
  • 2020-12-20 13:37

    You can do interactive rebase git rebase -i. Man page has exactly what you want:

    http://git-scm.com/docs/git-rebase#_splitting_commits

    0 讨论(0)
  • 2020-12-20 13:41

    Now in the latest TortoiseGit on Windows you can do it very easily.

    Open the rebase dialog, configure it, and do the following steps.

    • Right-click the commit you want to split and select "Edit" (among pick, squash, delete...).
    • Click "Start" to start rebasing.
    • Once it arrives to the commit to split, check the "Edit/Split" button and click on "Amend" directly. The commit dialog opens.
    • Unselect the files you want to put on a separate commit.
    • Edit the commit message, and then click "commit".
    • Until there are files to commit, the commit dialog will open again and again. When there is no more file to commit, it will still ask you if you want to add one more commit.

    Very helpful, thanks TortoiseGit !

    0 讨论(0)
  • 2020-12-20 13:44

    Use git rebase --interactive to edit that earlier commit, run git reset HEAD~, and then git add -p to add some, then make a commit, then add some more and make another commit, as many times as you like. When you're done, run git rebase --continue, and you'll have all the split commits earlier in your stack.

    Important: Note that you can play around and make all the changes you want, and not have to worry about losing old changes, because you can always run git reflog to find the point in your project that contains the changes you want, (let's call it a8c4ab), and then git reset a8c4ab.

    Here's a series of commands to show how it works:

    mkdir git-test; cd git-test; git init

    now add a file A

    vi A

    add this line:

    one

    git commit -am one

    then add this line to A:

    two

    git commit -am two

    then add this line to A:

    three

    git commit -am three

    now the file A looks like this:

    one
    two
    three
    

    and our git log looks like the following (well, I use git log --pretty=oneline --pretty="%h %cn %cr ---- %s"

    bfb8e46 Rose Perrone 4 seconds ago ---- three
    2b613bc Rose Perrone 14 seconds ago ---- two
    9aac58f Rose Perrone 24 seconds ago ---- one
    

    Let's say we want to split the second commit, two.

    git rebase --interactive HEAD~2

    This brings up a message that looks like this:

    pick 2b613bc two
    pick bfb8e46 three
    

    Change the first pick to an e to edit that commit.

    git reset HEAD~

    git diff shows us that we just unstaged the commit we made for the second commit:

    diff --git a/A b/A
    index 5626abf..814f4a4 100644
    --- a/A
    +++ b/A
    @@ -1 +1,2 @@
     one
    +two
    

    Let's stage that change, and add "and a third" to that line in file A.

    git add .

    This is usually the point during an interactive rebase where we would run git rebase --continue, because we usually just want to go back in our stack of commits to edit an earlier commit. But this time, we want to create a new commit. So we'll run git commit -am 'two and a third'. Now we edit file A and add the line two and two thirds.

    git add . git commit -am 'two and two thirds' git rebase --continue

    We have a conflict with our commit, three, so let's resolve it:

    We'll change

    one
    <<<<<<< HEAD
    two and a third
    two and two thirds
    =======
    two
    three
    >>>>>>> bfb8e46... three
    

    to

    one
    two and a third
    two and two thirds
    three
    

    git add .; git rebase --continue

    Now our git log -p looks like this:

    commit e59ca35bae8360439823d66d459238779e5b4892
    Author: Rose Perrone <roseperrone@fake.com>
    Date:   Sun Jul 7 13:57:00 2013 -0700
    
        three
    
    diff --git a/A b/A
    index 5aef867..dd8fb63 100644
    --- a/A
    +++ b/A
    @@ -1,3 +1,4 @@
     one
     two and a third
     two and two thirds
    +three
    
    commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
    Author: Rose Perrone <roseperrone@fake.com>
    Date:   Sun Jul 7 14:07:07 2013 -0700
    
        two and two thirds
    
    diff --git a/A b/A
    index 575010a..5aef867 100644
    --- a/A
    +++ b/A
    @@ -1,2 +1,3 @@
     one
     two and a third
    +two and two thirds
    
    commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
    Author: Rose Perrone <roseperrone@fake.com>
    Date:   Sun Jul 7 14:06:40 2013 -0700
    
        two and a third
    
    diff --git a/A b/A
    index 5626abf..575010a 100644
    --- a/A
    +++ b/A
    @@ -1 +1,2 @@
     one
    +two and a third
    
    commit 9aac58f3893488ec643fecab3c85f5a2f481586f
    Author: Rose Perrone <roseperrone@fake.com>
    Date:   Sun Jul 7 13:56:40 2013 -0700
    
        one
    
    diff --git a/A b/A
    new file mode 100644
    index 0000000..5626abf
    --- /dev/null
    +++ b/A
    @@ -0,0 +1 @@
    +one
    
    0 讨论(0)
  • 2020-12-20 13:44

    Here is how to split one commit in IntelliJ IDEA, PyCharm, PhpStorm etc

    1. In Version Control log window, select the commit you would like to split, right click and select the Interactively Rebase from Here

    2. mark the one you want to split as edit, click Start Rebasing

    3. You should see a yellow tag is placed meaning that the HEAD is set to that commit. Right click on that commit, select Undo Commit

    4. Now those commits are back to staging area, you can then commit them separately. After all change has been committed, the old commit becomes inactive.

    0 讨论(0)
  • 2020-12-20 13:44

    A quick reference of the necessary commands, because I basically know what to do but always forget the right syntax:

    git rebase -i <sha1_before_split>
    # mark the targeted commit with 'edit'
    git reset HEAD^
    git add ...
    git commit -m "First part"
    git add ...
    git commit -m "Second part"
    git rebase --continue
    

    Credits to Emmanuel Bernard's blog post.

    0 讨论(0)
提交回复
热议问题