如何更新镜像的git存储库

问题描述

我们正在从本地存储库迁移到Azure。

我们已经克隆并镜像了一次存储库:

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

但是现在,对于所有CI / CD流程(仅在开发过程中),我们在新存储库上进行了很多更改。 但是与此同时,开发人员继续在旧的存储库(位于多个分支)上进行工作和提交。

有没有一种方法可以将原始存储库“合并”到新存储库上?或者至少仅采用旧版本库的当前版本,然后再次应用所有新更改?

您将如何“更新”我们的副本?

解决方法

为什么需要合并存储库?当链接两​​个存储库时,git没有什么不能做的...

您可以在镜像存储库中简单地使用以下git命令:

git pull

通过这种方式,git automaticcaly将更新并合并您当前所在分支的所有远程更改。

现在,如果仅修改了develop分支,则可以在镜像存储库的该分支中使用上面的命令,然后git为您完成工作(只需检查文件之间的冲突),然后在需要开发人员合并它们要开发的分支机构,请记住,开发的历史记录已修改,但这不会影响结果。 考虑一下,如果要查看其他分支中开发分支的新增更改,则需要将开发分支与其他分支逐一合并。

,

您可以将两个存储库都添加到与远程服务器相同的本地存储库中,并在此处合并它们的分支。遵循以下原则:

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]还要检查this answer,以快速了解两个遥控器之间的区别。


如果您有一个本地克隆并将两个存储库设置为远程(例如使用@jingx的答案),则可以编写脚本来检查可以将哪些分支推送到new

(注意:我将保留名称newold,如@jginx建议命名两个遥控器,您想用{{1}中的数据更新new中的分支};在下面的脚本中,您可能想用old搜索和替换new并用origin替换old

  • whatever name you chose for the remote that points to the decomissioned repo允许您列出所有现有的分支名称:
git for-each-ref
  • # 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]
  • 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]是否是ref1的祖先(因此:如果ref2可以快速转发到ref1):
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]) ]

示例用法:

# 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

git for-each-ref refs/remotes/old --format="%(refname:lstrip=3)" | while read branchname; do bash check.sh $branchname done > actions.sh 现在是一个文件,其中包含一些要执行的动作的列表;您可以查看它,然后选择应应用和忽略的内容。

如果就地对其进行编辑(例如:删除或注释要忽略的行),则只需调用actions.sh即可运行它。