DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Git Forks And Upstreams: How-to and a Cool Tip

Git Forks And Upstreams: How-to and a Cool Tip

If you use git-o-sphere, it's important to keep your upstream maintainers happy. This guide will cover the forking techniques you should implement to do just that.

Nicola Paolucci user avatar by
Nicola Paolucci
·
Feb. 16, 17 · Tutorial
Like (10)
Save
Tweet
Share
9.74K Views

Join the DZone community and get the full member experience.

Join For Free

There are tons and then some useful guides on how to keep your forks updated against the upstream repositories (and if you're wondering why you would want to use forks in an enterprise setting, check out a few reasons here). In this blog, I will introduce you to few aspects of how forking interacts with upstream: the basics, the gotcha's, and an cool tip. To top it off I will then make you very jealous, or very eager, the choice is yours. Interested? Read on.

The Base Workflow to Keep Up-to-Date and Contribute

Let me start by detailing a common setup and the most basic workflow to interact with upstream repositories.

In a standard setup, you generally have an origin and an upstream remote — the latter being the gatekeeper of the project or the source of truth to which you wish to contribute to.

First, verify that you have already setup a remote for the upstreamrepository — and hopefully an origin too:

git remote -v origin git@bitbucket.org:my-user/some-project.git (fetch) origin git@bitbucket.org:my-user/some-project.git (push)


If you don't have an upstream you can add it simply with the remotecommand:

git remote add upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git


Verify that the remote is added correctly:

git remote -v origin git@bitbucket.org:my-user/some-project.git (fetch) origin git@bitbucket.org:my-user/some-project.git (push) upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (fetch) upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (push)


Now you can collect the latest changes of the upstream repository with fetch (repeat this every time you want to get updates):

git fetch upstream


(If the project has tags that have not merged to master you should also do: git fetch upstream --tags.)

Generally, you want to keep your local master branch as a close mirror of the upstreammaster and execute any work in feature branches (that might become pull requests later).

At this point it does not matter if you use merge or rebase, the result will typically be the same. Let's use merge:

git checkout master git merge upstream/master


When you want to share some work with the upstream maintainers, you branch off master, create a feature branch and when you're satisfied you push it to your remote repository.

You can also use rebase instead, then merge to make sure the upstream has a clean set of commits (ideally one) to evaluate:

git checkout -b feature-x #some work and some commits happen #some time passes git fetch upstream git rebase upstream/master


If you need to squash a few commits into one you can use the awesome rebase interactive at this point.

After the above, publish your work in your remote fork with a simple push:

git push origin feature-x


A slight problem rises if you have to update your remote branch feature-x after you published it, because of some feedback from theupstream maintainers. You have a few options:

  • Create a new branch altogether with the updates from you and the upstream.
  • merge the updates from upstream in your local branch which will record a merge commit. This will clutter the upstream repository.
  • Rebase your local branch on top of the updates from upstream and do a force push onto your remote branch:
git push -f origin feature-x


Personally, I prefer to keep the history as clean as possible and go for option three, but different teams have different workflows. OBVIOUS ALERT!! You should do this only when working with your own fork. Rewriting history of shared repositories and branches is something you should NEVER do.

Tip of the Day: Ahead/Behind Numbers in the Prompt

After a fetch, git status shows you how many commits you are ahead or behind of the remote the branch it syncs to. Wouldn't it be nice if you could see this information at your faithful command prompt? I thought so too so I started tapping with my bash chopsticks and cooked it up.

Here is how it will look on your prompt once you configure it:

nick-macbook-air:~/dev/projects/stash[1|94]$


And this is what you need to add to your .bashrc or equivalent, just a single function:

function ahead_behind { curr_branch=$(git rev-parse --abbrev-ref HEAD); curr_remote=$(git config branch.$curr_branch.remote); curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3); git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|'; }


You can enrich your bash prompt with this new function ahead_behind to have the desired effect. I leave the colorization as an exercise for the reader (not to clutter the tip too much).

Sample prompt:

export PS1="\h:\w[\$(ahead_behind)]$"


Inner Workings

For those who like details and explanations here is how it works:

We get the symbolic name for the current HEAD i.e. the current branch:

curr_branch=$(git rev-parse --abbrev-ref HEAD);


We get the remote that the current branch is pointing to:

curr_remote=$(git config branch.$curr_branch.remote);


We get the branch onto which this remote should be merged to (with a cheap Unix trick to discard everything up to and including the last forward slash /):

curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);


Now we have what we need to collect the counts for the commits we are ahead or behind:

git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';


We use the age-old Unix tr to convert the TAB to a separator |.

Conclusions

I hope this basic walk-through on upstream is useful for those unfamiliar with the process. Also note that the latest uber-fresh Bitbucket Server release includes fork synchronization which basically relieves the developer from all the burden of keeping up to date with its forks, check it out!

Follow me @durdn and the awesome @AtlDevtools team for more DVCS rocking.

Fork (software development) Git Branch (computer science) workplace Upstream (software development)

Published at DZone with permission of Nicola Paolucci, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Strategies for Kubernetes Cluster Administrators: Understanding Pod Scheduling
  • Asynchronous Messaging Service
  • How To Set Up and Run Cypress Test Cases in CI/CD TeamCity
  • Microservices 101: Transactional Outbox and Inbox

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: