2
\$\begingroup\$

This is a Bash script that takes the name of a local Git repo and a remote server host/path, generates a bare repo, and copies the bare repo to a Git server located in another server.

Example usage:

centralize-git-repo.sh arepo user@gitserver:/srv/git

It generates a folder in server:/srv/git/arepo.git and adds the remote in the local repo.

#!/bin/bash
set -e

GIT="/usr/bin/git"
SCP="/usr/bin/scp"

if [ "$1" == "--help" ] | [ $# -eq 0 ] ; then
    echo "$0 [repo] [user@]hostname:[remote_git_path]"
    exit 0
fi

# Assign parameters
LOCAL_REPO=$(basename $1)
REMOTE_DIR=$2

# Checks if the repo exists in current directory.
if [ ! -d "${LOCAL_REPO}" ]; then
    echo "${LOCAL_REPO} is not a repo in current directory."
    exit 1
fi

# Checks second parameter is present
if [ ! "${REMOTE_DIR}" ]; then
    echo "Remote is missing, pass the target dir on the remote "
    echo " server as the second parameter as: user@server:/dir/../git/"
    echo ""
    echo "e.g.: $0 localrepo user@gitserver:/srv/git"
    exit 1
fi

######

# Creates a container for the bare repo
BARE_TMP_DIR=$(mktemp --quiet --directory)
NEW_REPO_DIRNAME=${LOCAL_REPO}.git
BARE_REPO_PATH=${BARE_TMP_DIR}/${NEW_REPO_DIRNAME}

mkdir ${BARE_REPO_PATH}

$GIT clone --bare ${LOCAL_REPO} ${BARE_REPO_PATH}/

$SCP -r ${BARE_REPO_PATH} ${REMOTE_DIR}

# add remote
cd ${LOCAL_REPO}
$GIT remote add origin ${REMOTE_DIR}/${NEW_REPO_DIRNAME}
$GIT remote -v

# clean
rm -rf ${BARE_TMP_DIR}
cd ..
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Wouldn't it be easier to initialize the bare repo on the server already? \$\endgroup\$
    – Vogel612
    Aug 3 '17 at 9:20
  • \$\begingroup\$ @Vogel612 Yes, It could be a bit easier as you don't need to create the temporal folder but you have to git push. It would be very similar to this process anyway: - Initialize a bare repo in the remote server, add the remote locally and push. \$\endgroup\$
    – marcanuy
    Aug 3 '17 at 12:58
1
\$\begingroup\$

Bug

First things first, this doesn't work:

if [ "$1" == "--help" ] | [ $# -eq 0 ] ; then

You need || there, not |.

Local bare repo + copy vs remote bare repo + push

I completely agree with @Vogel that it would be better to create the bare repo on the remote, and then push to it:

  • git push is the simplest and safest way to transport Git repo data
  • Working with temporary dirs is messy. If your script gets killed in the middle, the cleaning at the end may not be reached (this could be improved by using trap)
  • The local bare clone unnecessarily doubles the .git storage space locally

Usability

The current script must be run in the parent directory of a Git repo, as it is enforced by the [ ! -d "${LOCAL_REPO}" ] condition. This is not convenient, and it doesn't have to be that way.

You could make it work with any valid path by making these two simple changes:

# LOCAL_REPO=$(basename $1)
LOCAL_REPO=$1

# NEW_REPO_DIRNAME=${LOCAL_REPO}.git
NEW_REPO_DIRNAME=$(basename "$LOCAL_REPO").git

Quoting

It's a good practice to double-quote variables used in command arguments. For example instead of this:

LOCAL_REPO=$(basename $1)

It's good to make it a habit to write like this:

LOCAL_REPO=$(basename "$1")

(I trust you don't intend to ever create a repository with a space in the name, but this is still a good habit to pick up.)

The same goes for running the uses of $GIT and $SCP.

On the other hand, some quoting is unnecessary, for example you could write like this:

GIT=/usr/bin/git
SCP=/usr/bin/scp

if [ "$1" = --help ] || [ $# -eq 0 ] ; then

This is just for your information, it's ok the way you did it.

Only loosely related, but simply echo is the same as echo "".

Changing directories in scripts

Be careful with changing directories in scripts. If an error happens in the middle of the operation, the next operation may find itself in an unexpected directory (in the absence of adequate error handling).

Changing directories can become safer using (...) sub-shells. For example instead of this:

cd ${LOCAL_REPO}
$GIT remote add origin ${REMOTE_DIR}/${NEW_REPO_DIRNAME}
$GIT remote -v
cd ..

You could write like this (without the cd .. at the end):

(
    cd ${LOCAL_REPO}
    $GIT remote add origin ${REMOTE_DIR}/${NEW_REPO_DIRNAME}
    $GIT remote -v
)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.