Splitting up commits makes the process of reviewing often easier, since you can create several merge requests or review every commit one by one.
So when you find out that you have portions of the code that you initially didn't intend to change or when you do some refactoring along the current changes, you can use one of the following processes to split up the changes into several commits in a logical order:
#1 Splitting up the last n commits into m commits
#2 Adding changes to a previous commit
2.1 While adding new changes
2.2 Selectively reverting changes
#3 Splitting up previous commits (by moving changes or creating new commits)
3.1 Splitting up
3.2 Adding to later commits
#4 Reordering commits
n
commits into m
commits If you decide to split up the n
commits after you have finished working on a feature.
Step by step:
git reset --soft HEAD~n
(or git reset --soft <commit hash>
)git reset -- <file path>
.git add -p
Only adding changes to the index instead of removing from the index
- Depending on the number of commits and the amount of changes, it might be easier to only add changes from the working directory.
- Then use
git reset HEAD~n
in step 1 and then only add the desired changes for every commit in step 2 instead of removing selectively.
git commit --amend
You can also use git fixup to selectively revert previous changes and add them to another commit
git reset <commit hash> <file path>
.git reset --patch <commit hash> <pathspec>...
Let's say you have three commits a -> b -> c
and want to reset changes of commit b
and apply them to commit c
git log --oneline
to get the required <hash of commit a>
git reset
:git reset <hash of commit a> app/assets/stylesheets/pagination.sass
git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: app/assets/stylesheets/pagination.sass
Untracked files:
(use "git add <file>..." to include in what will be committed)
app/assets/stylesheets/pagination.sass
fixup
to add the commit to delete the file to b
git add
fixup
to add the the changes to commit c
git rebase -i --autosquash master
Even though the process in #1 could be used for this it can become quite tedious if you have a large commit and might have already done this and just want to refine some changes afterwards.
If you just want to split up the last commit into several commits just follow the process in "How to split up a git commit"
git rebase -i
e
git stash
git rebase --continue
to edit the next commitgit stash pop
If you are finished with splitting up, reordering the commits may give them a more logical appearance, especially if the changes depend on each other. Then:
Use git rebase -i HEAD~n
for n
being the number of commits to reorder.
Vim shortcuts to reorder
If you use vim these shortcuts will come in handy
ddp
will move current line downdd
, moving the cursor,p
will paste the line at the current cursor position