DEV Community

loading...
Cover image for Git commands to keep a fork up to date

Git commands to keep a fork up to date

Phil Nash
Developer evangelist for Twilio and Authy. I write JavaScript and Ruby. Probably listening to ska punk right now. console.log('🍻');
Originally published at philna.sh on ・4 min read

I’ve seen the following tweet about git making its way around Twitter recently:

And it’s true, you can do most of your work with those commands.

What if you want to fork and contribute to an open source project (perhaps even this site!) on GitHub, GitLab or BitBucket though? You’re going to need a few more commands so that you can keep your fork up to date, namely remote, fetch and merge. Let’s see how they are used.

Fork away

When you fork a project, you make a copy of it under your own namespace. To work with the project you then clone the repository to your own machine. Let’s use a repo I have forked as an example: Twilio’s Node.js package. After forking, we clone the repo:

git clone git@github.com:philnash/twilio-node.git

Enter fullscreen mode Exit fullscreen mode

We can now see the first use case for remote. Run git remote in the twilio-node directory and we see the following:

git remote
origin

Enter fullscreen mode Exit fullscreen mode

OK, that’s not too useful, it just shows we have one remote repo called “origin”. Running it again with the --verbose flag shows a bit more information:

git remote --verbose
origin  git@github.com:philnash/twilio-node.git (fetch)
origin  git@github.com:philnash/twilio-node.git (push)

Enter fullscreen mode Exit fullscreen mode

That’s better, this shows that the remote repository is the one we cloned and that we can fetch from and push to it.

Making changes

When contributing something back to the repo, it is easiest to do so on a branch. That keeps the master branch clean and makes it easy to keep up to date. Setting up your changes is covered by the six commands Cory listed in his tweet; you create a new branch with branch, checkout the branch, make the changes you want, commit as many times as necessary and finally push the branch to the origin, your fork. Then you can create your pull request and hope it gets accepted.

Sometime later down the line you find you want to make another pull request, but the original repo has moved on. You need to update your fork so that you’re working with the latest code. You could delete your fork and go through the process of forking and cloning the repo again, but that’s a lot of unnecessary work. Instead, add the upstream repository as another remote for the repo and work with it from the command line.

Adding the upstream

To do this, we use the remote command again, this time to add a new remote. Find the original repo’s URL and add it as a new remote. By convention this remote is called “upstream” though you can call it whatever you want.

git remote add upstream git@github.com:twilio/twilio-node.git

Enter fullscreen mode Exit fullscreen mode

Now if we inspect the repo’s remotes again, we will see both the origin and the upstream. You can use -v as a shortcut for --verbose.

git remote -v
origin git@github.com:philnash/twilio-node.git (fetch)
origin git@github.com:philnash/twilio-node.git (push)
upstream    git@github.com:twilio/twilio-node.git (fetch)
upstream    git@github.com:twilio/twilio-node.git (push)

Enter fullscreen mode Exit fullscreen mode

Fetching the latest

To bring the repo up to date, we can now fetch the latest from the upstream repo. It looks like this:

git fetch upstream
remote: Counting objects: 6427, done.
remote: Compressing objects: 100% (549/549), done.
remote: Total 6427 (delta 5156), reused 5105 (delta 4939), pack-reused 934
Receiving objects: 100% (6427/6427), 2.54 MiB | 1.28 MiB/s, done.
Resolving deltas: 100% (5399/5399), completed with 391 local objects.
From github.com:twilio/twilio-node
   6a6733a8..73656c50 master -> upstream/master

Enter fullscreen mode Exit fullscreen mode

git fetch downloads objects and refs from the repository, but doesn’t apply it to the branch we are working on. We want to apply the updates to the master branch, so make sure it is checked out.

git checkout master

Enter fullscreen mode Exit fullscreen mode

Merging it all together

To bring the master branch up to date with the remote merge the remote’s master branch into our own, like so:

git merge upstream/master

Enter fullscreen mode Exit fullscreen mode

If you have kept your work off the master branch this will go ahead smoothly. Finally push these updates to the fork so that it is up to date too.

git push origin master

Enter fullscreen mode Exit fullscreen mode

Now everything on the master branch of the fork is up to date. If you need to update a different branch, substitute the branch name master for the branch you are working with.

Shortcuts

If you have been working with git pull then you may have already seen a potential shortcut. pull is the combination of fetch and merge, so to perform these two actions in one command you can run:

git pull upstream master

Enter fullscreen mode Exit fullscreen mode

Fork happy

That’s all you need to know for keeping your fork up to date when contributing to open source. Add the upstream as a new remote repo, fetch the upstream repo and merge the branch you want to update.

For more detail on the various commands here, take a look at “Working with Remotes” from the Pro Git book.

And remember, if you get stuck with something with git, check out Oh shit, git! for all your expletive based ways to save yourself.

Happy forking!

Discussion (27)

Collapse
nickytonline profile image
Nick Taylor (he/him)

Thanks for sharing Phil! I created an alias for rebasing my forks of upstream remotes, which is what I currently do when working on dev.to's codebase. gitaliases.iamdeveloper.com/#file-... if you're interested.

Collapse
philnash profile image
Phil Nash Author

Ooh, a pull --rebase upstream master. Pro level upstream work!

I have shied away from too many aliases from my git setup, purely so that I can remember the actual commands and work with git anywhere. That's quite the list you have there and I bet I and others would learn quite a bit from reading through the ones you have aliased, which I assume you also use relatively frequently. Have you thought of writing anything up on all of these?

Collapse
nickytonline profile image
Nick Taylor (he/him)

I probably should. I mention it to others occasionally in comments. At the moment though, I've started, in my head at least, a "Converting dev.to's search to Preact", so gotta get that one out first 😉, i.e. github.com/thepracticaldev/dev.to/...

Keep up the awesome posts and looking forward to the next one. 🔥

Collapse
xexyl profile image
xexzy

Another reason to shy away from aliases is that you get used to the aliases and then what happens when you use another system and forget you set up aliases ? Don’t laugh! It easily happens and although it’s never caused me a problem it’s because I don’t use aliases that have any behaviour modifications that matter; I for example alias gdb to ‘gdb -q’ but that’s harmless if it’s not on another install. Other commands can be far more devastating.

They can be useful but always always always remember this : aliases are for convenience and although I wouldn’t say it’s convenience XOR security the two do fight each other. And this includes data security too! But as pointed out if you rely too much on aliases you train your brain to remember those and forget the real invocations. This can particularly be a problem with different OSes more generally whether you go to a different job or maybe even worse is you use both on a daily basis.

Btw it’s happened that some people have gone to a new job but the previous say admin had set up aliases or config files that modify behaviour that has devastating consequences. This could even be deliberate and even compromise the network even installing a back door before parting! Yes that’s beyond development but still worth remembering.

Collapse
nickytonline profile image
Nick Taylor (he/him)
Collapse
ben profile image
Ben Halpern

Super useful post Phil, folks are going to love this one.

Collapse
philnash profile image
Phil Nash Author

Thanks Ben! I'm mainly glad I managed to write something again, it's been too long!

Collapse
philnash profile image
Phil Nash Author

Ah, you mean for the case in which we use git in a truly distributed fashion, rather than the centralised way we've evolved with services like GitHub? I could, but I trust that anyone who knows what they're doing cloning aross local networks probably also knows how to add remotes, fetch and merge as well!

Collapse
xexyl profile image
xexzy

Or even private repos. I have quite a few on my server that are only accessible by ssh and I have ingress filtering - and don’t allow password logins either.

You shouldn’t assume that people know all the features even if they do know how to do something else. And even if they do know they might benefit from it or think of something new! That’s the beauty of the Unix philosophy and the pipe.

Thread Thread
philnash profile image
Phil Nash Author

Yup, but this article had quite a narrow scope. I could have explained much, much more, but I wanted to keep the message tight.

Collapse
xexyl profile image
xexzy

Just a suggestion for the document itself and at the least future documents :

Add a prompt to the command invocation (that is prepend) to make it clearer what you type and what the output is. Maybe it’s because I am an old timer and also quite literal but my favourite example of that is quotes and a dot inside in say a VI editor tutorial i.e. ‘dd.’ which would repeat the action.

Anyway whether it’s a ‘>’ or a ‘$’ or if you want to go old school even a ‘%’ (brings back memories heh) it would make the article a bit clearer.

Cheers.

Collapse
philnash profile image
Phil Nash Author

You know, I go and back and forward over this a bit.

I understand that the prompt gives a little more context, which is useful. However, I also know that people like to copy and paste from articles online (you can argue this is bad, but that's not my choice) and sometimes will copy the prompt as well and the command won't work.

I've even seen someone implement a $ function in their terminal that just passes through the arguments to run them so that they aren't caught out by the inclusion of a $ in online instructions (can't find the article about this right now, but I swear it exists).

For me right now, I like to make things copy-pastable without any surprises, so I'll keep the article as it is. I appreciate the feedback though, thank you.

Collapse
hamzaanis profile image
Hamza Anis


git pull upstream master

works just fine in most of the scenarios.

Collapse
philnash profile image
Phil Nash Author

That is correct and why I talked about using pull right near the end of the post. It’s nice to know how to use the other commands too though, which is why I wanted to explain them too.

Collapse
hamzaanis profile image
Hamza Anis

Yes I read that too. You explained everything and it was good but in my opinion it was better to discuss pull first and explaining things further. BTW it's a great article.

Thread Thread
philnash profile image
Phil Nash Author

Ah, cool, thanks. I thought it was better to build up from the basic components before unveiling the shortcuts. Thanks for reading!

Thread Thread
xexyl profile image
xexzy

Background is almost always better - but you could add a note at first that there’s a built in command that does both i.e. merges the two commands. And no I can’t help it. I love punning!

Collapse
bbasile profile image
Basile B.

Actually if the fork is solely used to make PRs you never have to push the ~master branch to the fork. Just don't forget to pull the origin before making a change a push the feature/fix branch on your fork... Although if you're a bit obsessional it's nice to have the GH message "this fork is even with its origin"

Collapse
philnash profile image
Phil Nash Author

That may be true, but as it's only one extra command then why not do it? And I am that obsessed about the text on GitHub telling me it's up to date!

Collapse
enguerran profile image
enguerran 🐐💨

And a big 🍻 for talking about fetch and merge before offering the pull shortcut. It's much more didactic.

Collapse
codemouse92 profile image
Jason C. McDonald

Awesome! I needed this info twice last week, and now I have a handy reference for all those cases in the future! Bravo!

Collapse
philnash profile image
Phil Nash Author

If only I'd written it last week then! Hopefully it will help in the future though, I know I always end up checking back on my own blog posts to remind myself. So if it helps anyone else, that's even better.

Collapse
dimpiax profile image
Dmytro Pylypenko

TIP

Also you can set default upstream for your push, by:
git push -u remote branch, i.e.: git push -u origin master.

So every next time, you have to push in short way git push.

Collapse
philnash profile image
Phil Nash Author

That is true, though when you clone a repo the default upstream is normally set to origin master. This is useful if you want to work on a different remote branch.

When I push a branch that I want to make into a pull request, I normally do git push -u origin new-branch which allows me to easily make updates to that branch.

Thanks for adding the tip!

Collapse
moopet profile image
Ben Sinclair

I don't think I could use git with those 6 commands anyway, because 'log' is so fundamental.