I'm working on a shell script I wrote to automatically sync a local branch with its upstream branch. It does this by:
- first checking that there are no uncommitted changes locally, then
- fetching any missing commits from the upstream,
- doing a merge (or rebase), and finally
- pushing the result back upstream.
The problem is that if the upstream is non-bare, there is a good chance that the push will fail with the infamous ! [remote rejected] master -> master (branch is currently checked out)
error, due to the default value of receive.denyCurrentBranch
. Therefore I would like to programmatically predict in advance whether the push will fail in this manner, so that I can push using a different refspec (e.g. $branch:refs/remotes/$src/$branch
). This would at least guarantee that the remote contains the latest commits, even if they are not in the remote's working tree.
This could be done as follows:
- connect to the remote server
- jump through some hoops to calculate the absolute path of the repo on the remote, and
chdir
to it - execute
git config core.bare
- if it returns
true
then we know we won't get the[remote rejected]
error on push - if it returns
false
, execute another command to determine which branch is currently checked out on the remote, to see if it matches the one being pushed
But this makes the assumption that ssh
(or some other remote mechanism) is available for execution of arbitrary commands on the remote end, and it requires calculating the absolute path to the repo on the remote too, so it's not a clean, generally applicable solution.
Another option is just to attempt the push, spot when it fails in this manner, and retry with the modified refspec. But that's a bit ugly too. Is there a cleaner solution?