4

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?

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
J4N
  • 19,480
  • 39
  • 187
  • 340
  • 1
    Does this answer your question? [How to update a git clone --mirror?](https://stackoverflow.com/questions/6150188/how-to-update-a-git-clone-mirror) – flaxel Oct 01 '20 at 14:39
  • @flaxel the other question clearly state this is not a bare repository, and also it doesn't have LFS, so I'm not sure how this could be applied? – J4N Oct 05 '20 at 09:33
  • @flaxel also, in my case, I've now 2 remotes, and I've been working on another checkout(not a bare one), so I need to retrieves the changes done on the new repository I guess? – J4N Oct 05 '20 at 09:42

3 Answers3

1

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.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
  • because, my understanding is that I've a bare repository, and and I've 2 differents remotes with differents changes. So how to retrieve changes from the 2 remotes? If you execute the code I provided, the new repository is even not listed as remote, so how could I take the changes on the remote and update the new remote with them? We have also branches with features on which we are waiting on different customers to integrate. It's never gonna happen to have only one develop. It's because of this I'm asking how to take the full old remote and update the full new repo. – J4N Oct 05 '20 at 10:55
  • ok, so you need to update one repository to the other, let me say the mirror one with git pull command , then you can clone this updated repo to the bare one . :) – Zig Razor Oct 05 '20 at 10:58
0

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
jingx
  • 3,698
  • 3
  • 24
  • 40
  • any chance to do this for all the branches ? Because we have quite a few developers, some branches are only existing on the old repository, some branches are not existing **anymore** on the old repository(and should be deleted) – J4N Oct 01 '20 at 13:36
  • For sure you can rinse and repeat that merge step until you have all the branches done. It's no different from typical merges you do everyday. – jingx Oct 01 '20 at 13:59
  • that's not my question: I don't want to look myself for all branches that are still existing on both side, check which one have been created and deleted. Also, I think that since I've LFS and a bare repo, I cannot checkout a specific branch. – J4N Oct 01 '20 at 17:03
  • I see what you mean now. The word "merge" albeit quoted in OP made me think you had changes you actually needed to merge. If what you want is basically incrementally migrate all the changes, you can keep running `git push --remote`. – jingx Oct 01 '20 at 17:34
  • I'm not sure you have to work in a bare repo. Bare repo would make more sense when you are setting up a public repo for multiple users to push to. Clearly this repo is just an intermediary for you to migrate changes. I don't see any reason why you can't just clone a normal one and work in it. – jingx Oct 01 '20 at 17:36
0

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

LeGEC
  • 46,477
  • 5
  • 57
  • 104