Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add git remote only if it doesn't exist

Tags:

git

Is there a easy way for a script to detect if a remote already exists and add it only if it doesn't? A plumbing command or porcelain flag?

When running git remote add foo https://example.net with an existing remote I get:

fatal: remote foo already exists.

Ideally there would be a flag such as --if-not-exists or --update-if-exists but I couldn't find any in the documentation.

I'm thinking of grepping the output of git remote but is there a better way?

like image 894
ext Avatar asked Sep 14 '19 12:09

ext


3 Answers

git config remote.foo.url >&- || git remote add foo

git's written to handle closed fd's so you don't need >/dev/null, just close it, config sets a return code when you ask for a nonexistent config.

like image 192
jthill Avatar answered Oct 19 '22 20:10

jthill


Another answer suggested in 2019:

If the remote already exist:

$ git remote add foo https://example.net
fatal: remote foo already exists.
$ echo $?                               
128

That does change with Git 2.30 (Q1 2021): exit codes from "git remote add/rename"(man)
were not usable by scripted callers.

See commit 9144ba4 (27 Oct 2020) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit ecf95d9, 09 Nov 2020)

remote: add meaningful exit code on missing/existing

Signed-off-by: Ævar Arnfjörð Bjarmason

Change the exit code for the likes of "git remote add/rename"(man) to exit with 2 if the remote in question doesn't exist, and 3 if it does. Before we'd just die() and exit with the general 128 exit code.

This changes the output message from e.g.:

fatal: remote origin already exists.  

To:

error: remote origin already exists.  

Which I believe is a feature, since we generally use "fatal" for the generic errors, and "error" for the more specific ones with a custom exit code, but this part of the change may break code that already relies on stderr parsing (not that we ever supported that...).

The motivation for this is a discussion around some code in GitLab's gitaly which wanted to check this, and had to parse stderr to do so: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2695

It's worth noting as an aside that a method of checking this that doesn't rely on that is to check with "git config"(man) whether the value in question does or doesn't exist. That introduces a TOCTOU race condition, but on the other hand this code (e.g. "git remote add(man)) already has a TOCTOU race.

We go through the config.lock for the actual setting of the config, but the pseudocode logic is:

read_config();
check_config_and_arg_sanity();
save_config();  

So e.g. if a sleep() is added right after the remote_is_configured() check in add() we'll clobber remote.NAME.url, and add another (usually duplicate) remote.NAME.fetch entry (and other values, depending on invocation).

git remote now includes in its man page:

EXIT STATUS


On success, the exit status is 0.

When subcommands such as 'add', 'rename', and 'remove' can't find the remote in question, the exit status is 2.
When the remote already exists, the exit status is 3.

On any other error, the exit status may be any other non-zero value.

like image 2
VonC Avatar answered Oct 19 '22 19:10

VonC


Use git remote show <remote>:

$ git remote show origin && echo ok || echo err
* remote origin
  Fetch URL: …
  Push  URL: …
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master rebases onto remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)
ok

$ git remote show xxx && echo ok || echo err
fatal: 'xxx' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
err
like image 1
phd Avatar answered Oct 19 '22 20:10

phd