apc
apc

Reputation: 1607

Check if git remote exists before first push

I'm writing a bash script and I need a test to see whether a given remote exists.

Suppose, for concreteness, that I want to test whether the remote faraway exists. If I've pushed something to faraway, I can do if [ -d .git/refs/remotes/faraway ]; then .... But as far as I can see, the alias faraway can still be defined even if .git/refs/remotes/faraway does not exist.

One other option is to parse through the output of git remote and see if faraway appears there. But I'm wondering whether there is an easier way of checking whether faraway is defined, regardless of whether .git/refs/remotes/faraway/ exists.

Upvotes: 43

Views: 30624

Answers (5)

Patrick Callahan
Patrick Callahan

Reputation: 11

If the remote is defined in .git/config, you can avoid pinging the remote server with git remote.

if git remote | grep -e "^faraway$" > /dev/null; then ... fi

The ^ and $ prevent matching similar names like longagoandfaraway.

Upvotes: 0

Christopher
Christopher

Reputation: 44244

One thought: You could test exit status on git ls-remote faraway. This will actually force communication with the remote, instead of just looking for its presence or absence locally.

if ! git ls-remote --exit-code faraway > /dev/null 2>&1; then
    ....
fi

Upvotes: 50

Gabriel Staples
Gabriel Staples

Reputation: 52767

The fastest and most-reliable way I've found in bash is this:

if timeout 30s git ls-remote --tags > /dev/null 2>&1; then
    # Note: it takes 2~4 sec to get to here.
    echo "git server IS available"
else
    # Note: it takes 30 seconds (as specified by `timeout`) to get to here.
    echo "git server is NOT available"
fi

Optionally increase the timeout 30s value to a larger number of seconds if your server is unable to respond under normal conditions within that amount of time.

For a full and detailed explanation, see my main answer here: Fastest way to check if a git server is available.

Note that I do not recommend using the --exit-code option, due to what @Jo Liss said here:

-h is a great idea. However, --exit-code is not the right choice here. The man page says: Exit with status "2" when no matching refs are found in the remote repository. This means that git ls-remote --exit-code "$REPO_URL" will fail for an empty repo that has only just been initialized with git init.

Also, I most-definitely recommend using --tags over -h or --heads in order to make this command as fast as possible when the git server is available. See my speed comparisons in my question here. Here they are again for your convenience. Using --tags consistently takes 2~4 sec, whereas --heads takes 3~10 sec.

# 4~25 sec
# 218467 lines
time git ls-remote | wc -l

# 3~18 sec
# 218076 lines
time git ls-remote --refs | wc -l

# 3~10 sec
# 43337 lines
time git ls-remote --heads | wc -l

# 2~4 sec
# 9769 lines
time git ls-remote --tags | wc -l

# 0.002 ~ 0.008 sec
# But worthless! It passes even if the remote is not available!
time git ls-remote --get-url

# 4~25 sec
# 1 line
time git ls-remote origin HEAD

See also my comment here:

@torek, for your reference, it's a massive > 100 GB GitHub Enterprise mono-repo, with 218467 objects returned by git ls-remote. I tested repeatedly, and git ls-remote --tags is very consistently a lot faster than time git ls-remote --symref origin HEAD. I suspect it's because there are fewer --tags than --heads to search through and the latter requires finding all --heads and then linearly searching through them to find the match to HEAD. (I'm guessing on the linear search assumption here--trying to explain observations I am seeing, not predict observations I am not).

Upvotes: 2

tig
tig

Reputation: 27800

Another way to check if faraway is defined in .git/config:

if git config remote.faraway.url > /dev/null; then
  …
fi

To check if faraway isn't defined, prefix the condition with !:

if ! git config remote.faraway.url > /dev/null; then
  …
fi

Upvotes: 48

reubano
reubano

Reputation: 5363

If the remote is defined in .git/config, you can avoid pinging the remote server with git remote.

if git remote | grep faraway > /dev/null; then
  ...
fi

Upvotes: 11

Related Questions