Search code examples
gitgit-bashgit-remote

git - updating remotes - Do I need to provide the remotes name?


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.

  1. Is this unusual?
  2. What happens if there are 2 or more remotes?

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.


Solution

  • 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.