Skip to content

Instantly share code, notes, and snippets.

@rabellamy
Forked from ianmariano/git-fork-sync
Last active June 24, 2016 19:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rabellamy/d8d417ad5fbe5264c9959258f1ecf46b to your computer and use it in GitHub Desktop.
Save rabellamy/d8d417ad5fbe5264c9959258f1ecf46b to your computer and use it in GitHub Desktop.
Syncs your repo fork with the upstream integration and then pushes the synced integration to origin. Presumes you have an 'upstream' remote which is from whence your fork was created. Put on your path and chmod a+x it then do: git fork-sync
#!/bin/bash
VERSION="20150504"
usage() {
cat << __EOF
$0 usage:
$0 [options]
Where [options] include:
-h|--help Show this help
-v|--version Show the version and exit
-r|--remote REMOTE_NAME Fetch only this remote
-t|--topic TOPIC_BRANCH And rebase integration onto this
topic integration after syncing.
-u|--upstream REMOTE_NAME And push synced integration here too
-c|--checkout TOPIC_BRANCH When done, checkout this branch
-s|--mine-only Only sync with your origin
-a|--fetch-all With -s, also fetch all remotes
If remote is not specified, all remotes are fetched
and your local integration is rebased with upstream/integration
then pushed to your origin.
If remote is specified, only that remote is fetched
and your local integration is rebased to remote/integration
then pushed to your origin.
-t|--topic may be used multiple times
-u|--upstream may be used multiple times
-s|--mine-only will ignore other options except -a
If you only have an origin, git fork-sync will only sync with
your origin as if you specified -s or --mine-only.
git fork-sync will fail if you do not have at least origin defined
as a remote.
__EOF
exit 1
}
REMOTE=""
MINE_ONLY=""
FETCH_ALL=""
TOPICS=()
UPSTREAMS=()
CHECKOUT=""
while [ $# -ge 1 ]; do
key="$1"
shift
case $key in
-h|--help)
usage
exit 1
;;
-v|--version)
echo "git-fork-sync version $VERSION"
echo""
exit 0
;;
-r|--remote)
REMOTE="$1"
shift
;;
-t|--topic)
TOPICS+=("$1")
shift
;;
-u|--upstream)
UPSTREAMS+=("$1")
shift
;;
-c|--checkout)
CHECKOUT="$1"
shift
;;
-s|--mine-only)
MINE_ONLY="yes"
;;
-a|--fetch-all)
FETCH_ALL="yes"
;;
*)
usage
exit 1
;;
esac
done
if output=$(git status --untracked-files=no --porcelain) && [ -z "$output" ]; then
echo "Working directory is clean."
else
echo "You have uncommitted changes."
exit 1
fi
echo "Checking connectivity:"
all_remotes=`git remote`
cr=($all_remotes)
have_origin=""
have_upstream=""
for r in $all_remotes; do
echo -n " $r... "
if [ "origin" == "$r" ]; then
have_origin="yes"
elif [ "upstream" == "$r" ]; then
have_upstream="yes"
fi
if git ls-remote --exit-code $r &>/dev/null; then
echo "ok"
else
echo "FAILED!"
exit 1
fi
done
if [ -z "$have_origin" ]; then
echo "You do not have an origin defined."
exit 1
fi
if [ 1 == ${#cr[@]} ]; then
echo "You only have an origin, falling back to single mode."
MINE_ONLY="yes"
fi
if [ -z "$have_upstream" ]; then
echo "You do not have an upstream, falling back to single mode and fetching all."
MINE_ONLY="yes"
FETCH_ALL="yes"
fi
set -e
git checkout integration
if ! [ -z "$MINE_ONLY" ]; then
if [ -z "$FETCH_ALL" ]; then
echo "Only syncing with your origin."
git pull --rebase=preserve
echo -n "Now pruning remote origin... "
git remote prune origin && echo "done."
else
echo "Getting all remote history and syncing only with your origin."
git pull --rebase=preserve --all
echo "Pruning all remotes:"
for r in $all_remotes; do
echo -n " $r... "
git remote prune $r && echo "done"
done
fi
exit 0
elif [ -z "$REMOTE" ]; then
echo "Getting all remote history."
git pull --rebase=preserve --all
echo "Syncing with upstream."
git rebase -p upstream/integration
git push origin integration
echo "Pruning all remotes:"
for r in $all_remotes; do
echo -n " $r... "
git remote prune $r && echo "done"
done
else
echo "Only syncing $REMOTE with integration."
git pull --rebase=preserve
git fetch $REMOTE
git rebase $REMOTE/integration
git push origin integration
git remote prune $REMOTE
fi
if [ ${#TOPICS[@]} -gt 0 ]; then
echo "Rebasing topic branches:"
for t in ${TOPICS[@]}
do
echo " onto $t"
git rebase -p integration $t
done
git checkout integration
fi
if [ ${#UPSTREAMS[@]} -gt 0 ]; then
echo "Pushing synced integration:"
for u in ${UPSTREAMS[@]}
do
echo " to $u"
git push $u integration
done
fi
if ! [ -z "$CHECKOUT" ]; then
git checkout $CHECKOUT
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment