close icon
daily.dev platform

Discover more from daily.dev

Personalized news feed, dev communities and search, much better than whatโ€™s out there. Maybe ;)

Start reading - Free forever
Continue reading >

๐Ÿค• Git Visualized: Forked a Repo, Now The Original Has More Commits

๐Ÿค• Git Visualized: Forked a Repo, Now The Original Has More Commits
Author
Saqib Ameen
Related tags on daily.dev
toc
Table of contents
arrow-down

๐ŸŽฏ

Let's consider a scenario where you are contributing to an open-source project.

  1. You forked a project.
  2. You cloned the repository.
  3. You made some changes.
  4. You pushed the changes.
  5. Time to create a pull request โ€” but the original master branch has more commits now. ๐Ÿค•

What to do now? You might have struggled with this scenario at some time in your career. Most of the beginners still do.

To all those struggling, this guide will help you handle such a situation and help you understand the underlying concepts of git as well. So let's get started!

๐Ÿ‘จโ€๐Ÿ’ป Current State of Git Branches

Below is the visualization of the current scenario.

visualization of branches in git

For those who are not familiar with the concepts of upstream, it's not the local or the forked one, it points to the original repository on GitHub. It is not set by default. You need to manually link your cloned repo with upstream.

๐ŸŽฏ Pointing to The Upstream

For the sake of convenience let's assume two repos:

Original โ€” https://github.com/dailydotdev/daily
Fork โ€” https://github.com/saqibameen/daily

Below is the git command to do it.

# Add Upstream Remote.
git remote add upstream https://github.com/dailydotdev/daily.git

# Fetch latest updates from it.
git fetch upstream

Remember that, those updates will be in upstream/[BRANCH_NAME]. With that done, now your remote pointers in local repo look like below:

The Remote Branch Links

At this stage, we have upstream/master available locally and we need to bring the new commits (namely, E and F in our diagram) to our feature branch. We have two options here:

  • Merge
  • Rebase

Both can be used to obtain the end result โ€” get the latest updates from upstream/master and keep our commits as well.

๐Ÿ”— Using git merge

Make sure you are on the feature branch. Use the following command to do the merge:

# Merge upstream/master to feature branch. 
git merge upstream/master

If there are any conflicts in the merge, resolve them. Otherwise, just write the merge-commit message and you are all set. Behind the scene, your feature branch looks like this. The last commit is the merge commit that you do whenever you perform a merge.

Git merge resultant feat branch

Just a little convoluted history, which you might not want. All you want is your changes on top of the upstream/master followed by a push origin and a pull request.

๐Ÿ— Using git rebase

git rebase is something I find a perfect fit for such a scenario. With it, you get a clean git history and nothing more. So, instead of the git merge, you can do the following:

# Rebase feature branch on top of upstream/master
git rebase upstream/master

Now, take a look at how the feature branch looks like:

Use of git rebase

Did you notice the stars(*) on top of commit C and D? If you are not familiar with git rebase, I used them to indicate that these commits are a copy of the original commits C & D.

๐Ÿค” Take a look at the feature branch โ€” probably exactly what we need for PR; not anything more. Perfect!

UPDATE:
You can also use the following command to achieve this all in one command.

git pull upstream master --rebase

๐Ÿš€ Push the changes

Let's see in both cases how git push works. After that, we only need to create a PR.

# Push changes to the origin. 

#In case of merge
git push origin feature

# In case of rebasing
git push --force origin feature

Did you notice the --force flag in case of rebasing? It is because we are re-writing history. ๐Ÿ™ˆ

The feature branch initially had the following commits:

A โ€” B โ€” C โ€” D

With rebase, we changed it to:

A โ€” B โ€” E โ€” F โ€” C* โ€” D*

So, not only we created copies of C, and D commits, we also put E, and F at their original positions: git history is changed. That's why we need --force flag. Otherwise, you might get an error.

Because of the fact that git rebase copies commits and changes history, don't use it when you shared those commits with the team. Be careful while using it. A perfect scenario is when you haven't shared your work with anyone.

๐Ÿ™Œ Wrap Up!

Learning through use-cases is the best way to master anything. You don't only solve that problem but also get to understand the usage of tech involved in the process.

I hope this post will help you not only get through this situation but also understand how git merge and git rebase differ and where to use them. If you have any questions, feel free to drop them in the comments section below.


๐Ÿ‘‹ Follow us on Twitter to stay up-to-date!

Thanks to Daily, developers can focus on code instead of searching for news. Get immediate access to all these posts and much more just by opening a new tab.

Daily Poster

Why not level up your reading with

Stay up-to-date with the latest developer news every time you open a new tab.

Read more