When using Git to manage our code, we often need to make some modifications to our already committed content, such as:
- Deleting a commit
- Adjusting the order of commits
- Merging several commits into one commit
- Modifying the content of a previous commit
- Cherry-picking several commits from someone else’s branch
For the scenarios mentioned above, we typically use Git’s interactive rebase and cherry-pick to resolve them. Let’s look at each one individually. My current commits are as follows:
The displayed order of commits is in reverse, meaning my current HEAD is pointing to the bottom commit, ebf6bd1, while 24e87cf is the earliest commit.
Set Editor
When performing an interactive rebase in Git, you can specify the editor to use. By default, Git will use the system’s default editor, but you can change it through various methods.
Temporarily specify an editor
GIT_EDITOR=vim git rebase -i HEAD~3
Set the editor globally
You can set the default editor to your preferred one by using the following command:
git config - global core.editor "nano"
You can replace nano with your desired editor, such as vim, code — wait (Visual Studio Code), or subl -w (Sublime Text).
Using GIT_SEQUENCE_EDITOR
Another variable is GIT_SEQUENCE_EDITOR, which is specifically for interactive rebasing. If you want to use a different editor during the interactive rebase, you can specify it like this:
GIT_SEQUENCE_EDITOR=nano git rebase -i HEAD~3
Set in configuration file
You can also add a line in the Git configuration file to specify the editor directly. Open your Git configuration file, typically located at ~/.gitconfig, and add under the [core] section:
[core]
editor = nano
Example:
If you want to use Visual Studio Code as your default editor, you can run:
git config - global core.editor "code - wait"
This way, Git will automatically open the editor in Visual Studio Code during interactive rebases.
Deleting a commit
Adjusting commit order
For independent commits, you can open Git’s interactive rebase and adjust the order in the editor. For example, to adjust the order of the last two commits:
git rebase -i HEAD~2
This command means to open the last two commits before the current HEAD in an interactive way. By entering vim, you can manually rearrange the order of these two commits, as shown in the diagram.
Merging several commits into one commit
For instance, if I want to merge the later update binary commits into the first update binary commit: d1250db, I would run:
git rebase -i HEAD~7
Then, change pick
to s
in front of the commits I want to merge. This way, those two commits will be combined into the earlier d1250db.
Modifying the content of a previous commit
If we need to modify the content of a previous commit, we can also use:
git rebase -i HEAD~7
Change pick
to e
to edit that commit. When you save, it will prompt you.
At this point, we have two options:
- Directly modify the files, then use
git add
to stage the changes, followed bygit commit --amend
to update the commit. If you want to replace the previous commit message, you can also usegit commit --amend -m "Specify new commit message"
. - Alternatively, we can revert the changes made in that commit by using
git reset HEAD^
, which indicates reverting to the current HEAD commit. This way, all changes from that commit will return to the working directory. We can then modify the files here. However, the HEAD will now point to the commit before our edited commit. After making changes and usinggit add
to stage them, you can usegit commit -m "commit message"
to submit new changes that overwrite the old ones or usegit commit --amend
to add changes. However, because of the reset, the additional changes will be added to the commit before the one we edited.
Once completed, remember to use git rebase --continue
to proceed with the rebase.
Pick Other branch commit
When there are several commits on someone else’s branch that you want to merge into a target branch, first switch to the target branch using git checkout
, then use git cherry-pick
.
git checkout target-branch
Now, cherry-pick the commit by commit_hash:
git cherry-pick <commit_hash>
Cherry-picking Multiple Commits
You can also cherry-pick a range of commits or multiple specific ones:
- Range of commits:
git cherry-pick <start_commit>^..<end_commit>
- Multiple specific commits:
git cherry-pick <commit1_hash> <commit2_hash> <commit3_hash>
Handling Conflicts
If a cherry-pick operation leads to conflicts, Git will pause the process, and you will need to resolve the conflicts manually:
- You'll see which files have conflicts;
- open them and resolve the issues.
- After resolving conflicts, stage the changes:
git add <file_with_conflicts>
- Complete the cherry-pick operation:
git cherry-pick --continue
If you decide not to complete the cherry-pick due to conflicts or any other reason, you can abort it:
git cherry-pick --abort
Conclusions
When we have many co-workers on the same project, and the code managed by git, the operation on git commit are required when we deal with some situations, so mastering these techniques will be very helpful for our work with Git.
You can read another great article here.
If there are any mistakes, feel free to point them out and provide feedback. Thanks.