-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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