A Practical Guide to Git Rebase and Force Push with Lease | Chandrashekhar Kachawa | Tech Blog

A Practical Guide to Git Rebase and Force Push with Lease

Git

Git is an incredibly powerful version control system, but sometimes you might find yourself in a situation where you need to rewrite your commit history. Perhaps you made a commit with sensitive information, introduced a bug that you want to completely erase, or simply want to clean up your feature branch before merging. This article will guide you through the process of safely removing unwanted commits using git rebase -i and pushing your changes with git push --force-with-lease.

Finding the Commit to Remove

The first step is to identify the commit you want to remove. git log --oneline is your best friend here. It provides a concise, single-line summary of each commit, making it easy to spot the one you’re looking for.

git log --oneline

You’ll see output similar to this:

a1b2c3d Commit message for feature X
e4f5g6h Another commit
h7i8j9k Commit to be removed
l0m1n2o Initial commit

From this output, identify the short commit ID of the commit you wish to remove. In our example, let’s say we want to remove h7i8j9k.

Rewriting History with Interactive Rebase

Now that you have the commit ID, you can start the interactive rebase process. The command is git rebase -i <commit-id>. Crucially, you need to use the commit ID of the commit immediately before the commit you want to remove.

In our example, if we want to remove h7i8j9k, the commit before it is l0m1n2o. So, the command would be:

git rebase -i l0m1n2o

This will open an editor (usually your default Git editor) with a list of commits. It will look something like this:

pick h7i8j9k Commit to be removed
pick e4f5g6h Another commit
pick a1b2c3d Commit message for feature X

# Rebase l0m1n2o..a1b2c3d onto l0m1n2o (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) for each commit
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to re-use the original merge
# .       commit's message and also its authorship (when applicable).
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here, that commit will be lost.
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

To remove the commit h7i8j9k, simply change the word pick to drop next to its commit ID:

drop h7i8j9k Commit to be removed
pick e4f5g6h Another commit
pick a1b2c3d Commit message for feature X

Save and close the editor. Git will then apply the rebase, effectively removing the specified commit from your history.

Pushing Your Changes Safely

After a rebase, your local branch’s history will diverge from the remote repository’s history. A regular git push will fail because Git detects this divergence. You’ll need to force push your changes. However, a simple git push --force can be dangerous, especially in collaborative environments, as it overwrites the remote branch without checking if anyone else has pushed changes in the meantime.

This is where git push --force-with-lease comes in. It’s a safer alternative because it will only force push if the remote branch is exactly as you expect it to be. If someone else has pushed changes to the remote branch since you last pulled, git push --force-with-lease will fail, preventing you from accidentally overwriting their work.

git push --force-with-lease origin <your-branch-name>

Replace <your-branch-name> with the actual name of the branch you are working on (e.g., main, develop, feature/my-new-feature).

Conclusion

Rewriting Git history with git rebase -i and pushing with git push --force-with-lease are powerful techniques for maintaining a clean and concise commit history. While these commands offer great flexibility, it’s crucial to use them with caution, especially when working on shared branches. Always ensure you understand the implications of your actions, and when in doubt, communicate with your team members. By following these steps, you can effectively manage your Git history and keep your repositories tidy.

Latest Posts

Enjoyed this article? Follow me on X for more content and updates!

Follow @Ctrixdev