'What tool should I use to split git commit into multiple ones?

I've coded a feature spanning thousand of modified lines in a project, and now it all ended up in one big commit (I've squashed the work-in-progress commits). Now I'd like to split the changes into multiple commits for easier review/possibly multiple PRs.

Some files contain multiple changes that should end up in different commits, so I am looking for a WYSIWIG editor using three-pane view, that would allow me to move some lines to the intermediate commit while seeing the previous and future version (+ some manual changes). I use IntelliJ IDEA for the development, so I imagine something similar to conflict resolution dialog.

I could switch to different branch/tag the single-commit version and do Git->Compare with Branch (and grab the changes from there), but I am looking for something of more convenience.

While this could be marked as off-topic/opinionated, I believe that a neutral suggestion for a different workflow might be valuable.



Solution 1:[1]

For IntelliJ I use this workflow:

  • Open the git log window or Alt + 9
  • Right click on commit you want to split ? Interactively Rebase from Here
  • Right click on commit you want to split ? Stop to edit or Alt + E
  • Start Rebasing
  • Right click to the current commit in the git log with the yellow label ??! ? Undo commit... alternatively execute git reset HEAD~1 in the terminal
  • Ctrl + K to select and commit your changes with the according message. Repeat as often as necessary until all changes are committed.
  • On the bottom right click: Rebase Stopped for Editing ? Continue

Solution 2:[2]

Not sure about a tool that lets you do this, but, as according to the git documentation you can split a commit using the builtin rebase function. Something like:

git rebase -i
...
pick abc1234 the commit I wanna keep
edit 5904fjl THE COMMIT I WANT TO SPLIT
pick alkj022 my latest commit to keep

After that run git reset HEAD^ and you can manually break out your changes into commits. You can use the git add --patch to more easily split your intra-file changes into commits. Or if your Intellij IDE has a good git GUI you can use that. The splitting, at least in my experience, has to be done from the command line.

Solution 3:[3]

I found an easy way in PyCharm/IntelliJ.

The idea consists in reverting twice the changes you want to extract (so it is like a negative and a positive in the photography domain), and then merge the first reverted commit in the common latest commit, in order to remove the changes from that commit.

The explanation here-below may seem complicated, but actually just few clicks are necessary to extract some changes from a commit:

  • First of all, open the git panel with Alt+9
  • Select the latest commit of the current branch in the bottom left panel. In the bottom right panel you will see the files that have been modified in this commit.

At this point your history is like:

commit_3
   ^ 
commit_2
   ^ 
commit_1
  • Shift-select the files that you want to extract in a separate commit
  • Right click / Revert Selected Changes
  • Commit those changes in a commit called e.g. temporary_reverted_commit
git add -u :/
git commit -m "temporary_reverted_commit"

At this point your history is like:

temporary_reverted_commit
   ^ 
commit_3
   ^ 
commit_2
   ^ 
commit_1
  • Then in the bottom side panel right click on that new commit, and click 'Revert commit', and name the commit your_extracted_changes.

At this point your history is like:

your_extracted_changes
   ^ 
temporary_reverted_commit
   ^ 
commit_3
   ^ 
commit_2
   ^ 
commit_1
  • Now rebase to merge temporary_reverted_commit in commit_3 : put fixup on the temporary_reverted_commit commit so that it will squash it with commit_3, and save and quit the rebasing interface.
git rebase -i origin/dev
your_extracted_changes
   ^ 
commit_3
   ^ 
commit_2
   ^ 
commit_1

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 wspurgin
Solution 3