I'm writing a script to update several hundred repository remotes due to a url change for our internal code hosting.
Some of these repositories have a different remote name (i.e. different than origin). Have tested not providing the remote name and the updated remote can be pinged but I don't understand the behavior.
Updating the remotes in a more well defined way is preferred and I've tried using bash to extract the origin name:
What the character between the remote name and address in below?
$ git remote -v
origin ssh://git@code_hosting_site.com/project_name/repo_name.git (fetch)
^^
Thanks for any help.
Is this normal?
"Normal" is a funny word. It's hard to define whether this is normal. It's a bit unusual to have one remote and not have it named origin
, but it's not an error, it's just odd.
What happens if there are 2 or more remotes?
That's up to you. git remote -v
will list all of them, so it's certainly possible to extract them that way. You can also use:
git config --get-regexp 'remote\..*'
to list all of them. You might even want to add --local
to make sure that only remotes defined in the local .git/config
file are listed, in case some crazy user has defined a remote in her global configuration. (I assume you don't want to attempt to update any such entries.)
Note, too, that each remote can define both a URL and a push URL. These configuration names are case-insensitive, so you should fold case when looking for any remote.remote.url
and remote.remote.pushurl
settings "by hand" (if you write your own code to read a config
file), but you don't need to worry about that when using git config --get-regexp
or git remote -v
as those do the case-folding for you.
Hence, an sh or bash script to read through git config --get-regexp
output might use:
# fix - called with URLs that may need fixing. Argument $1 is the
# type (url or pushurl), argument $2 is the remote, $3 is the URL itself.
fix() {
local urltype=$1 remote="$2" url="$3"
local newurl
case $3 in
...) newurl="echo $url | sed ...";;
*) return;;
esac
git config "remote.$remote.$urltype" "$newurl"
}
git config --local --get-regexp 'remote\..*' | sort | while read -r lhs rhs; do
set -- $(echo $lhs | sed 's/\./ /g')
case $3 in
url|pushurl) fix $3 "$2" "$rhs";;
esac
done
(One can be a bit fancier in bash; the above works in POSIX sh—although the whole thing is quite untested. Of course you need to fill in the ...
parts as well.)
In general, remote names and URLs should not have white space in them. I used quotes above to handle cases where they might. (The git remote
command does not let you add a remote with a blank in its name, but does allow white-space in the URL.) The apparently-useless use of "sort" is to handle extreme cases: if the .git/config
file is very large, we could attempt to run git config
to change the configuration while git config --get-regexp
is still reading and printing the old configuration. In practice, it's probably not needed.