Back to when I started using Git, I was faced with this challenge. Someone has updated the upstream - how do I include the latest changes into my working branch?
The first approach is to pull master
and merge it into the working branch:
git pull origin master
Unfortunately, this way we're creating a new commit. What we really want is the following:
- Isolate our changes
- Get the latest upstream updates
- Apply the changes on top
- Resolve any conflicts
So we don’t want to merge our branch in the updated upstream but rebase on top of it.
First, let’s fast-forward the local master branch.
git checkout master
git pull
Now let’s head back to our working branch and do a rebase. All of our commits will be applied on top of the updated master
git checkout working_branch
git rebase origin master
You can completely ignore updating your local master branch and simply run
git rebase origin/master
. I like having my local master up to date so I opt for the first case.
At this point, we might have a few conflicts. We have a few options to deal with them:
git rebase --abort
will completely stop the rebase. The branch's initial state will be restored and we can start over. Nothing changed.git rebase --skip
will ignore the local commit that causes the problem. This is useful if the commit is not relevant anymore or if it’s a mistake.- or fix the conflicts, stage them and keep the rebase going with
git rebase --continue
Merging the branch
Having finished the work, it’s always a nice idea to 'squash' commits that that are not relevant in isolation. For example, if you have a few commits that are just fixing typos or minor CSS tweaks, it’s better to merge them into a single commit.
For this reason, doing an 'Interactive' rebase is really helpful
```txt title="Terminal"
git rebase -i master
Here’s an example of an interactive rebase prompt:
pick 07c6add Include password strength indicator in registration formm
pick d29b1fb Fix the regex
pick 317tt36 Minor typo
pick fa2fff3 CSS tweaks
# Rebase 44a7ee6..fa2fff3 onto 44a7ee6
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit’s log message
# x, exec = run command (the rest of the line) using shell
#
# 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.
#
Now you can do any of the following
- Pick - Keep the commit and move on to the next one
- Reword - Keep the commit, and get a prompt to update the message
- Edit - Keep the commit, but wait for you to update files and include them before moving on
- Squash - Merge into the commit above, and get a prompt to update the message
- Fixup - Same as
Squash
but it won’t prompt for a new message - Exec - Allows running shell commands against a commit
You can reorder these commits around if needed.
For this case, we'll:
- Reword and keep the first commit
- Squash the rest and discard the commit message by doing a
Fixup
r 07c6add Include password strength indicator in registration formm
f d29b1fb Fix the regex
f 317tt36 Minor typo
f fa2fff3 CSS tweaks
As a result our branch will contain a single meaningful commit on top of all the latest upstream changes.
Finally, we can push the branch to the remote repository and enjoy an up to date branch.
git push origin working_branch