In our previous lesson, you mastered the feature-branch workflow, learning to isolate your work and integrate it back into the main project using git merge. This process is fundamental, but the merge commits it creates can sometimes lead to a complex, branching history that is difficult to follow.
This lesson introduces git rebase, a powerful alternative for integrating changes that helps you maintain a clean, linear project history. You'll learn what rebasing does, how it differs from merging, and, crucially, when to use it safely. We will also distinguish it from another Git command, cherry-pick. Understanding these tools will elevate your version control skills, enabling you to produce repositories that are not just functional but also professional, readable, and easy to maintain—a key asset for collaborative research and your PhD applications.
Merging vs. Rebasing: Two Philosophies
Both git merge and git rebase solve the same problem: integrating changes from one branch into another. However, they do so with very different philosophies.
git mergejoins two branches together. As you saw, it creates a new "merge commit" that has two parents, preserving the exact historical record of when and how the branches were joined. Its philosophy is to be non-destructive and record history exactly as it happened.git rebaseworks by re-playing commits from one branch on top of another. Instead of creating a merge commit, it rewrites the project history by creating fresh copies of your commits in a new sequence. Its philosophy is to create a cleaner, linear history, as if you had done all your work in a straight line.
The following article from Atlassian provides an excellent conceptual overview with clear diagrams that illustrate this fundamental difference.
Merging vs. Rebasing | Atlassian Git Tutorial
This resource clearly illustrates the core difference between merging and rebasing. It will help you visualize how each command affects your project's commit history.
Please read the first three sections, up to "Interactive rebasing." Focus on the diagrams that show a forked history and how merge and rebase resolve it differently. Start with the introduction. Pay close attention to the explanation and diagram in The merge option. Contrast this with the explanation and diagram in The rebase option, which introduces the concept of rewriting history to create a linear path.
The Rebase Workflow: Keeping Your Branch Fresh
Let's return to the scenario from our last lesson. You create a feature branch, add-pca-plot, from main. While you're working, a collaborator pushes new updates to the main branch. Your feature branch is now "behind" main.
To incorporate the new changes from main into your feature branch, you can rebase.
- Check out your feature branch:
git checkout add-pca-plot - Rebase onto
main:git rebase main
Here's what Git does under the hood:
- It temporarily saves the commits that are unique to your
add-pca-plotbranch. - It resets your
add-pca-plotbranch to match themainbranch exactly. - It then re-applies your saved commits, one by one, on top of the tip of
main.
The result? Your feature branch now includes all the updates from main, but your own commits are at the tip, creating a straight, linear history. When you are finally ready to merge your feature into main, Git can perform a "fast-forward" merge, which simply moves the main branch pointer forward without creating a merge commit.
The following video provides an excellent visual demonstration of this process and compares the messy history of a merge-only workflow with the clean history of a rebase-then-merge workflow.
Git MERGE and REBASE: The Definitive Guide
This video, from The Modern Coder, provides a clear, animated explanation of how rebase re-anchors a feature branch and enables a clean, fast-forward merge.
Watch the section on rebasing from the rebase workflow. The side-by-side comparison at the end powerfully illustrates the benefit of a rebased history.
The Golden Rule of Rebasing
Rebasing is powerful, but with great power comes great responsibility. Because git rebase rewrites history (it creates new commits and abandons the old ones), it can be dangerous if used incorrectly. This leads to the single most important principle of using rebase:
Do not rebase commits that have been pushed to a public or shared branch.
When you rebase, you're changing the commit hashes. If you rebase a branch that others are also working on, your local history will diverge from the remote history. When you try to push, you'll have problems. If you force-push your rebased branch, your collaborators' work will be based on old commits that have vanished from the project's history, leading to confusion and complicated recovery efforts.
This rule is non-negotiable. Only rebase commits that exist only on your local machine. Once you share your work by pushing it, you should use git merge to incorporate future changes.
The resources below explain this rule and its justification in detail.
git rebase | Atlassian Git Tutorial
This section from the Atlassian tutorial covers the cardinal rule of rebasing.
Read the section titled Don't rebase public history. Understanding this principle is key to using rebase safely and professionally.
git rebase - Why, When & How to fix conflicts
This video from Philomatics provides a technical explanation for why rebasing pushed commits is a bad idea, focusing on how commit hashes change.
Watch the segment from the downsides to rebasing. It clearly explains the "Golden Rule" and the technical reasons behind it.
Distinguishing Rebase, Merge, and Cherry-pick
To solidify your understanding, let's clarify the roles of rebase, merge, and another command, cherry-pick.
A diagram comparing the outcomes of merge, rebase, and cherry-pick. White circles are original commits, green circles are new/copied commits, and the pink diamond is a merge commit.
git merge: Integrates an entire branch, preserving history and creating a merge commit if histories have diverged. Use this for combining a completed feature intomainor for synchronizing shared branches.git rebase: Moves an entire branch to a new base commit, rewriting history to be linear. Use this on your local feature branch to incorporate upstream changes frommainbefore you merge.git cherry-pick <commit-hash>: Copies a single commit from one branch and applies it as a new commit on another. It's useful when you need just one specific change (e.g., a critical bug fix) from another branch, but not the entire branch. Like rebase, it creates a new commit, so it should be used with care.
In short: merge and rebase deal with whole branches, while cherry-pick deals with individual commits. merge preserves history, while rebase and cherry-pick rewrite it by creating new commits.
Handling Conflicts During a Rebase
Just like with merging, you can encounter conflicts during a rebase if your changes and the new base branch's changes affect the same lines of code. However, the resolution process is slightly different.
When Git rebases, it applies your commits one by one. If a conflict occurs, the rebase will pause at the problematic commit and ask you to resolve it.
- Open the conflicted file(s) and edit them to the desired state, removing the conflict markers.
- Use
git add <conflicted-file-name>to stage the resolved file. - Instead of
git commit, rungit rebase --continue. Git will then proceed to apply the rest of your commits.
If at any point you get overwhelmed, you can cancel the entire operation with git rebase --abort. This will return your branch to the state it was in before you started the rebase.
This process is demonstrated very clearly in the following video.
git rebase - Why, When & How to fix conflicts
The Philomatics video you watched earlier also has an excellent, step-by-step walkthrough of resolving a rebase conflict.
Watch the section from worry about are conflicts. The presenter walks through a multi-conflict rebase, showing how to add the resolved file and then continue the rebase.
Conclusion
You've now added another sophisticated tool to your Git toolkit. git rebase allows you to maintain a clean, linear project history, which is highly valued in professional and academic research settings for its clarity and ease of navigation.
Here are the main takeaways:
- Rebase for a Clean History: Use
git rebaseon your local feature branches to incorporate updates frommain. This creates a linear history and allows for a clean, fast-forward merge. - Merge for Preserving History: Use
git mergeto integrate completed features into a public branch likemainor to synchronize branches shared with collaborators. - The Golden Rule: Never rebase a branch that you've pushed and shared with others. Rebasing rewrites history and can cause significant problems for your collaborators.
- Cherry-pick for single commits: Use
git cherry-pickwhen you need to copy a specific commit from one branch to another, rather than merging or rebasing the entire branch. - Conflict Resolution: Conflicts during a rebase are resolved commit-by-commit using
git addandgit rebase --continue.
By understanding the trade-offs between merging and rebasing, you can make informed decisions about how to manage your project's history, making your work more professional and easier for others (and your future self) to understand.
In our next lesson, we will shift focus from version control mechanics back to the analysis itself. You'll learn how to write a unit test for a data-cleaning function that you might extract from a notebook, ensuring your code is correct, robust, and reliable—a cornerstone of reproducible research.