Safely syncing your git fork to an upstream master

Safely syncing your git fork to an upstream master

Well there are about a million commands you can use to do this, but the notes on GitHub.com unfortunately create merges which are bad, bad when you are trying to maintain things, here is what they suggest. And note that this also works with private repos run by say Gitlab.
Fork from the GitHub.com repo, for example if you have a repo https://github.com/altercation/solarized to pick on the really cool solarized repo and you want to make a fork to say git@github.com:richtong/solarized just choose fork from the so called upstream. For Gitland, this is more like ssh://git@git._domain_.com/rtong/solarized where the private_repo is the domain where you are hosting things.
The syntax differences are a little important. The https means that you will have to type in your password. The colon syntax means that you are using ssh and so you do automatic key exchange if your ~/.ssh is set correctly, but that’s another post.
Now on at the command line, you can clone your own repo with git clone git@github.com:richtong/solarized
Now cd solarized to get into that new repo on your local machine
Here comes the tricky part, how do you first make sure your origin/master that is your fork is up to date.
First you want to declare the upstream with git remote add upstream https://github.com/altercation/solarized which gives your local repo two places to push things origin which is your fork and upstream which is the source of your fork. Or if you are using ssh, it is more like git remote add upstream ssh://git@git._domain_.com/solarized
Now when you want to sync your fork, the best command is to first git fetch upstream --prune which your local machine with all the data in https://altercation/solarized and also git fetch --prune which does the same for your fork’s in the cloud master. It’s a good practice to prune as when folks are deleting forks, without the prune, those old forks will live forever on your machine
Then you can sync it with git pull --rebase upstream/master which says take all your changes and put them at the top of the upstream/master. Note that you are doing a a fresh pull to make sure you have the latest copy from the server.
After you do this, you may want to simplify your many commits with git rebase upstream/master -i because this will put in an interactive dialog and you can squash various commits together and fix the edit names.
If these look good then git push -f will commit the rewrite to your branch and you are up to date with upstream/master on your own fork assuming you can write to your master branch.
If you do not have write permissions on the master fork, then you should do this all on a side fork and do a pull request in Github.com (aka a merge request in gitlab). So then the sequence looks something like
As an aside this makes it easy to do a pull request when you need to update the upstream because all your changes “bubble” to the top.
git remote add upstream ssh://git@github.com/richtong/repo
git checkout master
git checkout -b rich-changes

make some changes

git pull --rebase upstream/master
git rebase upstream/master -I
git push -f

This does mean that you have to be careful about the forced push. The best thing to do is to add a git hook so that it asks if you really want to force push that lives in special file that you need to set as executable.git/hooks/pre-push as explained by GIT hack
But it looks like the following, note that this is not itself in a repo and not checked in.

#!/bin/bash

protected_branch=’master’
current_branch=$(git symbolic-ref HEAD | sed -e ‘s,./(.),\1,’)
if [ $protected_branch = $current_branch ]
then
read -p “You’re about to push master, is that what you intended? [y|n] ” -n 1 -r < /dev/tty echo if echo $REPLY | grep -E ‘^[Yy]$’ > /dev/null
then
exit 0 # push will execute
fi
exit 1 # push will not execute
else
exit 0 # push will execute
fi

Share
%d bloggers like this: