4

I have a directory which contains over 20 git repositories. I have to change the remote origin url in each of them. I don't want to do it manually and would like to use following command:

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && git remote set-url origin git@euxxx-x-x-xxx01.xx.xx.xxx.com:/foo/bar/'{}'.git" \;

The problem is, that brackets {} are replaced by relative path, so I end up with following commands:

git remote set-url origin git@euxxx-x-x-xxx01.xx.xx.xxx.com:/foo/bar/./zaz/repo.git

but I need simply

git remote set-url origin git@euxxx-x-x-xxx01.xx.xx.xxx.com:/foo/bar/repo.git

How to achieve this?

Michał Kowalczyk
  • 358
  • 1
  • 5
  • 21

6 Answers6

9

A couple of times when i needed this, it was due to change in corporate DNS, which resulted in changing repo names. The following scripts helps to automate that. I don't like using directory names in loop because sometimes folder names are not the same as an actual repo name, that's why git is the best "source of truth".

The following script will replace all instances of "github.com" to "gitlab.com" in remote called "origin" recursively in all folders in a directory, where this script is located. You can override that with "SEARCH_ROOT" variable

#/bin/bash
SEARCH_ROOT=./
PATTERN=github.com
REPLACEMENT=gitlab.com
find "$SEARCH_ROOT" -type d -name "\.git"  -print | while read -r REPO;
do
  pushd "$REPO/../" > /dev/null || continue
  NEWURL=$(git remote get-url origin | grep "$PATTERN" | sed "s/$PATTERN/$REPLACEMENT/g")
  [ -z "$NEWURL" ] || git remote set-url origin "$NEWURL"
  popd > /dev/null || exit 1
done
Andrew
  • 3,912
  • 17
  • 28
  • Nice script, very useful! It'd be worthwhile to use the space character as the sed delimiter because it's visually clean and will never occur in a properly-formatted (i.e., escaped) URL. So something like this: `sed "s $PATTERN $REPLACEMENT g"` H/t https://stackoverflow.com/questions/16778667/how-to-use-sed-to-find-and-replace-url-strings-with-the-character-in-the-tar#:~:text=The%20space%20character%20works%20well,(i.e.%2C%20escaped)%20URL. – cal Nov 14 '22 at 16:27
6

Try something like this:

find * -maxdepth 0 -type d \( ! -name . \) -print | while read dir
do
    cd $dir && git remote set-url origin git@euxxx-x-x-xxx01.xx.xx.xxx.com:/foo/bar/$dir.git && cd ..
done

Which compacts down to the following one-liner:

find * -maxdepth 0 -type d \( ! -name . \) -print | while read dir; do cd $dir && git remote set-url origin git@euxxx-x-x-xxx01.xx.xx.xxx.com:/foo/bar/$dir.git && cd ..; done

Edit: Thanks to Mark Reed for pointing out a better way to iterate over dirnames.

Sebastian Lenartowicz
  • 4,695
  • 4
  • 28
  • 39
  • 1
    `for dir in $(ls)` is a lousy way to enumerate directories, with a variety of failure modes. I would use the OP's `find` command with `-print` instead of `-exec` and pipe it to `|while read dir`, which works as long as none of the dirs have newlines in their names. – Mark Reed Jul 12 '16 at 17:21
2

Remote Url value is stored in the config file. We have used Notepad++ to find&replace on the "Find In Files" tab to change all domain names in multiple repositories.

Find In Files screen will be something like that;

Notepad++ Sample Screen

Yusuf K.
  • 4,195
  • 1
  • 33
  • 69
1

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
Samar
  • 1,865
  • 12
  • 13
0

You could just use find * instead of find .. Then the pathname will match.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
0

You can use this shell script to change remote url Shell script to bulk change git remote url

  • 3
    It's much more helpful to paste the script inline than linking to an external resource that may be gone in the future. – rud Aug 29 '19 at 12:00