How to update a mirrored git repository

Viewed 1213

We are in the process of moving from a local repository to azure.

We have already cloned and mirrored the repository once:

git clone --bare https://xxx/xxx/old-repository.git
cd old-repository.git
git lfs fetch --all
git push --mirror https://xxx/xxx/new-repository.git
git lfs push --all https://xxx/xxx/new-repository.git

But now we have made a lot of changes on the new repository, for all the CI/CD process(only on develop). But meanwhile, developers have continued to work and commit on the old repository(on several branches).

Is there a way to "merge" the original repository on the new one? Or at least just take the current version of the old repository, and applies again all the new changes?

How would you "update" our copy?

3 Answers

Why you need to merge the repository? there is nothing that git can't do when 2 repository are linked...

You can simply use the this git command in the mirror repository:

git pull

In this way git automaticcaly will update and merge any remote changes of the current branch you're on.

Now if you are only modified develop branch, you can use the above command in this branch in the mirror repository, and git do the work for you (just check the conflict between files) then when you need your developers to merge their branches to develop, you keep in mind that the develop have the modified history, but this does not influence the result. Consider that if you want to see the added changes to develop branch in other branches, you need to merge the develop branch to the others, one by one.

You can add both repos to one same local repo as remotes, and merge their branches there. Something along these lines:

git clone -o new <url-to-new-repo> project
cd project
git remote add -o old <url-to-old-repo>
git fetch old
git checkout -b develop --track new/develop
git merge old/some-branch
# resolve conflicts as needed
git push new develop

[edit] check also this answer to have a quick overview of how much is different between your two remotes.


If you have a local clone with the two repositories set as remote (using for example @jingx's answer), you can write a script to check what branches can be pushed to new :

(note : I will keep the names new and old as @jginx suggested to name the two remotes, you want to update branches in new with data from old ; in the scripts below, you may want to search&replace new with origin, and old with whatever name you chose for the remote that points to the decomissioned repo )

  • git for-each-ref allows you to list all the existing branch names :
# the following will list all the branch names coming from 'old', without
# the leading 'old/' prefix (e.g : 'old/master' will be listed as 'master') :
git for-each-ref refs/remotes/old --format="%(refname:lstrip=3)"
  • git rev-parse --verify [refname] allows you to check if a ref exists :
if git rev-parse -q --verify new/$branchname > /dev/null; then
  echo "$branchname exists on new repo"
else
  echo "$branchname needs to be created on new repo"
fi
  • git merge-base --is-ancestor [ref1] [ref2] allows you to check if ref1 is an ancestor of ref2 (and hence : if ref1 can be fast forwarde to ref2) :
if git merge-base --is-ancestor new/$branchname old/$branchname; then
  echo "old/$branchname can be pushed to new repo as is"
else
  echo "old/$branchname and new/$branchname need to be merged,"
  echo "  or old/$branchname needs to be force pushed"
  echo "  or ignored ..."
fi
  • [ $(git rev-parse [ref1]) != $(git rev-parse [ref2]) ] allows you to check if two refs point at different commits

Here is an example script which puts these pieces together :

# file check.sh :

#!/bin/bash

branchname=$1

# if new/branchname does not exist: list it as a branch to be created
if ! git rev-parse -q --verify new/$branchname > /dev/null; then
    echo "git push new old/$branchname:refs/heads/$branchname  # create"
# if new/$branchname exists : check if it can be fast forwarded to old/$branchname
elif git merge-base --is-ancestor new/$branchname old/$branchname; then
    # check if the two branches are different :
    if [ $(git rev-parse old/$branchname) != $(git rev-parse new/$branchname) ]; then
        echo "git push new old/$branchname:refs/heads/$branchname  # update"
    fi
    # otherwise : nothing to do
else
    echo "# needs merging : new/$branchname and old/$branchname"
fi

sample usage :

git for-each-ref refs/remotes/old --format="%(refname:lstrip=3)" | while read branchname; do
  bash check.sh $branchname
done > actions.sh

actions.sh is now a file, which contains a list of some actions to perform ; you can review it, and choose what should be applied and ignored.

If you edit it in place (e.g : delete or comment the lines you want to ignore), you can simply run it by calling bash actions.sh.

Related