2

I have a bunch of git repos which have been moved to another host. I can update the remote for an individual repo with

git remote set-url origin <url>

How do I automate this for a few dozens of repos? Basically, I need to replace the hostname/path part of the url.

planetp
  • 14,248
  • 20
  • 86
  • 160
  • Does the old host still exist for other purposes? It might be easier to simply use your hosts file to make the old host name an alias for the new host name. – chepner Feb 14 '19 at 21:28
  • Yes, the old host still exists. How can I make it an alias via the hosts file? – planetp Feb 15 '19 at 06:40
  • You would have an entry like `123.456.789.10 newhost oldhost`, where the address is for the new host but old host would resolve to the same address. This is a global change, though, so only works if there is no reason for `oldhost` to ever resolve to its actual address. I don't think it fits your situation. – chepner Feb 15 '19 at 13:36

5 Answers5

9

While the git remote command can be used, it's easier to use sed against the config file in the repo .git directory.

Assuming the repos are all on old.example.com and are moved to new.example.com and you are currently in the parent directory containing all the repos:

find . -name ".git" -exec sed -i 's/old\.example\.com/new\.example\.com/g' {}/config \;

This will find all repos (with .git directories) then replace the old path with the new path on every line in the config file.

match
  • 10,388
  • 3
  • 23
  • 41
4

For simplicity let's pretend all repositories are in the same parent directory; run a loop over subdirectories getting the current URL, replacing host and putting the URL back:

cd parent_dir &&
for repo in *; do
    cd $repo &&
    remote=`git remote get-url origin` &&
    remote=`echo $remote | sed s/oldhost/newhost/` &&
    git remote set-url origin $remote &&
    cd .. # back to parent
done
phd
  • 82,685
  • 13
  • 120
  • 165
1

If your repositories are in a single directory, you can use a simple script like this:

for r in *; do
    git -C "$r" remote set-url origin "$(git -C "$r" remote get-url origin | sed s/old/new/)"
done

git -C <dir> tells Git to go into the repo directory before doing anything else. Then read the current remote URL and do the substitution using sed.
Needless to say, it's a good idea to make a backup before you start messing with configs of Git repositories.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
1

Answer from @match worked for me. Though I have to admit I've added something else from a different answer. People who are here using OSX, you might wanna add ' ' -e before the old and new part. So the whole thing could be:

    find . -name ".git" -exec sed -i '' 
 -e 's/old\.example\.com/new\.example\.com/g' {}/config \;

It worked for me and I got this from: invalid command code ., despite escaping periods, using sed

RVM
  • 2,237
  • 1
  • 13
  • 13
0

While finding .git directory and seding on config under that directory works perfectly, I like to let git handle this. This should work for any nested directories that may have git repositories. It will find any .git directories, cd to one directory above that .git and check for given remote type (origin by default) and modify the old remote with new remote. Usage is: ./thisscript 'git@github.com:oldcompany' 'git@github.com:newcompany' origin If your remote is origin, you don't need to pass the 3rd argument. Hope this helps people.

#!/usr/bin/env bash

# Usage: ${0} [OLD_REMOTE] [NEW_REMOTE] [REMOTE_NAME]

OLD_REMOTE="${1:-bitbucket.org:mybbcompany}"
NEW_REMOTE="${2:-github.com:myghcompany}"
REMOTE_NAME="${3:-origin}"

find "${PWD}" -type d -name '.git' | while read dir; do
  cd "${dir}/.."
  current_remote_url=$(git remote get-url "${REMOTE_NAME}")
  if grep "${OLD_REMOTE}" <<< "${current_remote_url}"; then
    new_remote_url=$(sed "s/${OLD_REMOTE}/${NEW_REMOTE}/" <<< "${current_remote_url}")
    echo "Changing ${current_remote_url} to ${new_remote_url}"
    git remote set-url "${REMOTE_NAME}" "${new_remote_url}"
  fi
done

Hope this will be useful for someone.

Samar
  • 1,865
  • 12
  • 13