- Published on
Part 9: Rewriting History with Git
- Authors
- Name
- Diego Herrera Redondo
- @diegxherrera
Introduction
Rewriting commit history can be a powerful tool for maintaining a clean and understandable project history. Git offers several commands to modify and refine the history, including git rebase
, git cherry-pick
, and git filter-branch
. However, these commands must be used with care to avoid disrupting the shared history.
1. Git Rebase for History Rewriting
git rebase
can be used not only for integrating changes but also for editing commit history. It helps create a linear and cleaner history by replaying changes on top of another branch.
Interactive Rebase
Interactive rebasing (git rebase -i
) allows you to:
- Reorder commits.
- Squash commits into a single one.
- Edit commit messages.
- Remove commits.
How to Use Interactive Rebase:
# Start an interactive rebase for the last 5 commits
$ git rebase -i HEAD~5
This opens an editor where you can specify actions for each commit:
- pick: Keep the commit as is.
- reword: Change the commit message.
- edit: Modify the content of the commit.
- squash: Merge the commit with the previous one.
- drop: Remove the commit.
Example: Squashing Commits
To combine multiple commits into one, mark the first commit as pick
and the subsequent ones as squash
.
2. Using Git Cherry-Pick
git cherry-pick
allows you to apply specific commits from one branch to another. This is useful for selectively moving features or fixes.
Basic Usage:
# Apply a specific commit to the current branch
$ git cherry-pick <commit-hash>
Practical Example: If a bug fix on feature-branch
needs to be applied to main
:
$ git checkout main
$ git cherry-pick <commit-hash>
This will copy the changes made in the specified commit and apply them to main
.
3. Git Filter-Branch for Advanced History Rewriting
git filter-branch
is a powerful command for rewriting history across all branches. It’s often used to:
- Remove sensitive data from commit history.
- Change email addresses or author information.
- Modify files across multiple commits.
Example: Removing a File from History:
$ git filter-branch --tree-filter 'rm -f path/to/file' -- --all
Note:
git filter-branch
is resource-intensive and can permanently alter history. Ensure you have backups and avoid using it on shared branches.
4. Precautions When Rewriting History
Rewriting history, especially on branches that have been shared with others, can cause significant issues. Always follow these precautions:
- Avoid rebasing or rewriting public branches: Use
rebase
andfilter-branch
only on local or private branches. - Communicate with your team: Inform your team before making changes to shared history.
- Back up your repository: Create a backup before running commands like
filter-branch
.
5. Practical Example: Rewording Commit Messages
- Start an interactive rebase:
$ git rebase -i HEAD~3
- Change
pick
toreword
for the commit you want to edit. - Save and close the editor.
- Enter the new commit message when prompted.
git reflog
to Recover from Mistakes
6. Using git reflog
tracks all changes made to HEAD and is invaluable for recovering lost commits or branches after rewriting history.
Recovering a Lost Commit:
# View reflog entries
$ git reflog
# Reset to a specific reflog entry
$ git reset --hard <commit-hash>
git filter-repo
7. Automating History Rewriting with git filter-repo
is a faster, more efficient alternative to git filter-branch
for advanced history rewriting tasks.
Installation and Basic Usage:
# Install git-filter-repo (requires Python)
$ brew install git-filter-repo
# Remove a file from history
$ git filter-repo --path path/to/file --invert-paths
Recap
- Rebase helps create a linear and cleaner history.
- Cherry-pick allows selective application of commits.
- Filter-branch and filter-repo provide powerful tools for extensive history rewriting.
- Reflog is a safety net for recovering changes.
Next Steps
In the next part, we’ll discuss Git Best Practices for Teams, focusing on collaboration tips, maintaining code quality, and integrating with CI/CD pipelines.
Stay tuned for Part 10: "Git Best Practices for Teams."