【问题标题】:How to update a mirrored git repository如何更新镜像的 git 存储库
【发布时间】:2021-01-17 04:44:27
【问题描述】:

我们正在从本地存储库迁移到 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 流程(仅在开发中)进行了很多更改。 但与此同时,开发人员继续在旧存储库上工作和提交(在几个分支上)。

有没有办法将原始存储库“合并”到新存储库上?或者至少只采用旧存储库的当前版本,并再次应用所有新更改?

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

【问题讨论】:

  • 这能回答你的问题吗? How to update a git clone --mirror?
  • @flaxel 另一个问题明确指出这不是一个裸存储库,也没有 LFS,所以我不确定如何应用?
  • @flaxel 同样,在我的情况下,我现在有 2 个遥控器,并且我一直在进行另一个结帐(不是一个空的),所以我需要检索对新的所做的更改我猜是存储库?

标签: git version-control git-remote


【解决方案1】:

您可以将两个存储库添加到与远程相同的本地存储库中,并在那里合并它们的分支。大致如下:

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

【讨论】:

  • 有没有机会为所有的分支机构这样做?因为我们有很多开发人员,有些分支只存在于旧版本库中,有些分支在旧版本库中不再存在(应该删除)
  • 确保您可以冲洗并重复该合并步骤,直到完成所有分支。这与您每天进行的典型合并没有什么不同。
  • 这不是我的问题:我不想自己寻找双方仍然存在的所有分支,请检查已创建和删除的分支。另外,我认为由于我有 LFS 和一个裸仓库,我无法签出特定的分支。
  • 我明白你的意思了。尽管在 OP 中引用了“合并”一词,但我认为您确实需要进行合并的更改。如果您想要的基本上是增量迁移所有更改,您可以继续运行git push --remote
  • 我不确定您是否必须在裸仓库中工作。当您为多个用户推送到公共存储库时,裸存储库会更有意义。显然,这个 repo 只是您迁移更改的中介。我看不出有什么理由不能克隆一个普通的并在其中工作。
【解决方案2】:

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

您可以在镜像仓库中简单地使用这个 git 命令:

git pull

这样 git 会自动更新并合并您当前所在分支的任何远程更改。

现在如果你只是修改了develop分支,你可以在镜像仓库的这个分支中使用上面的命令,然后git为你完成工作(只是检查文件之间的冲突)然后当你需要你的开发人员合并他们的要开发的分支,请记住开发具有修改的历史记录,但这不会影响结果。 考虑一下,如果你想在其他分支中看到添加到develop分支的更改,你需要将develop分支一一合并到其他分支。

【讨论】:

  • 因为,我的理解是我有一个裸存储库,并且我有 2 个不同的遥控器,有不同的变化。那么如何从 2 个遥控器中检索更改?如果你执行我提供的代码,新的存储库甚至没有被列为远程,那么我怎么能在远程上进行更改并用它们更新新的远程呢?我们也有分支机构,我们正在等待不同的客户整合这些功能。它永远不会发生只有一个发展。正因为如此,我在问如何使用完整的旧遥控器并更新完整的新仓库。
  • 好的,所以您需要将一个存储库更新到另一个存储库,让我用 git pull 命令说镜像一个,然后您可以将此更新的存储库克隆到裸存储库。 :)
【解决方案3】:

[edit] 还可以查看this answer 以快速了解您的两个遥控器之间的差异。


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

(注意:我将保留名称 newold,因为 @jginx 建议命名这两个遥控器,您想使用来自 old 的数据更新 new 中的分支;在下面的脚本中,您可能想用origin搜索和替换new,用whatever name you chose for the remote that points to the decomissioned repo替换old

  • 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] 允许您检查 ref 是否存在:
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]) ] 允许您检查两个 refs 是否指向不同的提交

这是一个将这些部分组合在一起的示例脚本:

# 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 现在是一个文件,其中包含要执行的一些操作的列表;您可以查看它,然后选择应该应用和忽略的内容。

如果您在原地编辑它(例如:删除或注释您想忽略的行),您只需调用 bash actions.sh 即可运行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 2015-07-16
    • 2012-08-14
    • 2013-01-29
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多