Do show the top-level working dir.
[git-shortcuts.git] / git-push-as-remote
blob2348b02ed122613b775fc3e2528805f63b6ff42a
1 #!/bin/sh
3 # Registers the current state of this repository in a remote repository under a special ID (a specially named remote which should be well-known as the refernce to this working copy/repository).
5 # Author: Ivan Zakharyaschev imz at altlinux dot org, March 2009, May 2010.
6 # I publish it under GPLv2 or later.
7 # (GPLv2 is chosen to match the license of the base tool, Git.)
9 # Doing so is useful for keeping track of the states of all your working copies.
11 # In a sense, there is almost NO SENSE in this command: one can type the corresponding (not so complex) refspec by hand,
12 # or set up the remote appropriately (see the comment at the end of file). Also, the alternatives allow more flexibility
13 # in how you name and store things remotely.
15 # The special ID for this repository should be set by
16 # "git config [ --global | ... ] shortcut-scripts.as-remote <newval>".
18 # For example, I use IDs corresponding to my working computers, e.g., @dell, @vaio, etc.
20 # In a sense, the action of this script is just the reverse of the action that would be done by some "git push" from a remote to this repository at the end: it would sync the state of this repository with remote-refs there (with a special ID--the remote name corresponding to this repository). This script does the same, but it is called from the other side.
22 # It's useful because it's not always possible (a server) or desirable (a portable disk) to set up a the corresponding repository at the other end, but you may wish to keep track of the states of your various working sites (repositories) for this project.
24 # Usage: passes all args to "git push", and adds its special refspec.
26 # This script together with the shortcut-scripts.as-remote parameter was made by me just to save typing/thinking over the special refspec.
28 set -e
30 usage() {
31 echo $"git push-as-remote ... , where ... are the args for \"git push\"."
32 echo $"This script does its best to detect the default case and to push to 'origin' then; but you might need to specify a remote explicitly."
33 echo $"You must have set \"git config shortcut-scripts.as-remote\" (possibly globally)."
34 echo $"This script will create on the remote side branches refs/remotes/AS_REMOTE/* tracking the state of this repo."
37 # Try to skip all options and see whether there is a non-option arg (which must be a remote).
38 # Not perfect: if an option has a parameter, and they are given without an equal sign in between,
39 # this will fool my code: it is'll be considered an argument (a remote).
40 # Well, then one will simply get an error message from "git push".
41 # That's because I can't parse "git push"'s options perfectly without a formal specification of the options,
42 # and I don't want to write up one by hand.
44 # (FR: git commands should print out the specification of options in the format accepted by "git rev-parse --parseopt",
45 # then one could more easily implement extensions to the git commands, like this one.)
46 readonly -a VERBATIM_ARGS=("$@")
47 while (( $# > 0 )); do
48 case "$1" in
49 -h|--help|--usage)
50 usage
51 exit 0
52 ;; # never reached actually
53 -*)
54 shift
55 continue
56 ;; # never reached actually
58 break
59 ;; # never reached actually
60 esac
61 done
62 if (( $# == 0 )); then
63 # A refspec can only be given in the command line for "push" after an explicitly specified remote,
64 # so since we pass our special refspec, we must pass a certain remote as well.
65 # If there are no args given (except for the options), then there is definitely no remote specified,
66 # so we emulate the "git push"'s default behavior (per manpage):
67 # "<remote> is the current branch's remote (or origin, if no remote is configured for the current branch)".
68 # Our refspec is "global", not related to the current branch, but spanning all the branches,
69 # so the only reasonable emulation is using "origin".
70 readonly -a args=("${VERBATIM_ARGS[@]}" origin)
71 else
72 readonly -a args=("${VERBATIM_ARGS[@]}")
75 readonly AS_REMOTE="$(git config shortcut-scripts.as-remote)"
76 if [[ ! "$AS_REMOTE" ]]; then
77 usage
78 exit 1
81 # It should do even "non-clean" ref updates (non-ff), because it's like a _mirroring_ tool.
82 git push "${args[@]}" "+refs/heads/*:refs/remotes/$AS_REMOTE/*"
84 # Alternatively to using this command and in order to save even more typing, you could set up the refspecs in the config, like this:
86 # [remote "origin"]
87 # url = /mnt/usbmem1/my/code/git-shortcuts/.git
88 # fetch = +refs/heads/*:refs/remotes/origin/*
89 # push = refs/heads/*:refs/heads/*
90 # push = +refs/heads/*:refs/remotes/@vaio/*
92 # This way you even don't loose the default possibly convenient behavior of "git push" (push only branches already present remotely):
93 # there is a special simple refspec for this behavior -- ":" (per manpage):
95 # The special refspec : (or {plus}: to allow non-fast forward updates) directs git to push "matching"
96 # branches: for every branch that exists on the local side, the remote side is updated if a branch of
97 # the same name already exists on the remote side. This is the default operation mode if no explicit
98 # refspec is found (that is neither on the command line nor in any Push line of the corresponding
99 # remotes file---see below).
101 # Warning: multiple "push = " lines seem not to work in git-1.5.5.5-alt1, should try putting it to .git/remotes/... .