Were you referred to this page to get your PR accepted? Scroll right to Git Rebase at FCC then!
git rebase
is an extremely useful tool that is all about rewriting git history, though most commonly used to squash multiple commits into one. While useful in this scenario, this is not the only function that the git rebase
command can perform. It in fact proves to be far more useful when used for the intended function that its name suggests: to essentially rebase a branch. Let me explain what I mean by that.
Let us say that you have a repository such as this:
--- Commit 5 ----------- auth branch
/
--- Commit 4 -------------- dev branch
/
--- Commit 1 ---- Commit 2 ---- Commit 3 -------------------------------- master branch
If you wanted to merge the auth
branch with the dev
branch, git will throw an error at you because your auth
branch is out-of-date: it doesn’t account for Commit 4. You’ll have to bring your branch up-to-date.
Git provides you with two methods to do this: the merge
command and the rebase
command. For an exploration of the merge
command, visit the relevant wiki article: Git Merge
Let’s run rebase
now:
$ git checkout auth
$ git rebase dev
The repo will now look like this:
--- Commit 5 --- auth branch
/
--- Commit 4 --------------------- dev branch
/
--- Commit 1 ---- Commit 2 ---- Commit 3 --------------------------------------- master branch
Do you see what happened? Git essentially saved the commits in the auth
branch, ‘removed’ it, and then created it again with the same commits after the commits in the dev
branch. This means that Commit 4
only exists in the dev
branch and not the auth
branch! And that is really all there is to it! This might seem a bit confusing at first, but try to understand the diagram. This is an extremely useful tool.
Git-Rebase at FCC
Preventing merge conflicts
If you contribute to the FCC codebase, or are planning to do it, always run this command before you make any changes in your local files and push them:
git pull --rebase upstream staging
If you don’t have upstream
set up, then run this command before you run the above command (git will throw an error because it doesn’t know what upstream is): git remote add upstream https://github.com/freecodecamp/freecodecamp.git
This will pull the latest changes from the FCC staging branch and rebase them with your fork’s staging branch so that you will not have any conflicts when opening the PR
Squashing
If you have multiple commits that you want to squash into one then follow the instructions for Squashing.
More detail
Git Rebase
Rebasing a branch in Git is a way to move the entirety of a branch to another point in the tree. The simplest example is moving a branch further up in the tree. Say we have a branch that diverged from the master branch at point A:
/o-----o---o--o-----o--------- branch
--o-o--A--o---o---o---o----o--o-o-o--- master
When you rebase you can move it like this:
/o-----o---o--o-----o------ branch
--o-o--A--o---o---o---o----o--o-o-o master
To rebase, make sure you have all the commits you want in the rebase in your master branch. Check out the branch you want to rebase and type git rebase master
(where master is the branch you want to rebase on).
It is also possible to rebase on a different branch, so that for example a branch that was based on another branch (let’s call it feature) is rebased on master:
/---o-o branch
/---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master
After git rebase master branch
or git rebase master
when you have checked out the branch, you’ll get:
/---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master
\---o-o branch
Git rebase interactive in the console
To use git rebase
in the console with a list of commits you can choose, edit or drop in the rebase:
- Enter
git rebase -i HEAD~5
with the last number being any number of commits from the most recent backwards you want to review. - In vim, press
esc
, theni
to start editing the test. - On the left hand side you can overwrite the
pick
with one of the commands below. If you want to squash a commit into a previous one and discard the commit message, enterf
in the place of thepick
of the commit.
pick 452b159 <message for this commit>
pick 7fd4192 <message for this commit>
pick c1af3e5 <message for this commit>
pick 5f5e8d3 <message for this commit>
pick 5186a9f <message for this commit>
# Rebase 0617e63..5186a9f onto 0617e63 (30 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but stop to edit the commit message.
# e, edit = use commit, but stop to amend or add commit.
# s, squash = use commit, meld into previous commit and stop to edit the commit message.
# f, fixup = like "squash", but discard this commit's log message thus doesn't stop.
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# 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
- Enter
esc
followed by:wq
to save and quit. - When rebase is stopped, make the necessary adjustments, then use
git rebase --continue
until rebase is successful - If it rebases successfully then you need to force push your changes with
git push -f
to add the rebased version to your github repo. - If there is a merge conflict, there are a number of ways to fix this, including following the suggestions in this guide. One way is to open the files in a text editor and delete the parts of the code you do not want. Then use
git add <file name>
followed bygit rebase --continue
. You can skip over the conflicted commit by enteringgit rebase --skip
, exit the git rebase by enteringgit rebase --abort
in your console.
Points to Note
Git Rebase is a very powerful feature. That being said, it is risky as well if it is not used in the right way.
Git rebase alters the commit history. So use it with care. If Rebasing is done in the remote repository, then it can create a lot of issues when other developers try to pull the latest code changes from the remote repository.
As much as possible try using Git Rebase only to rebase a local git repository.