将本地Git仓库推送到新的远程包括所有分支和标签


Push local Git repo to new remote including all branches and tags

我有一个本地Git仓库,我想推送到一个新的远程仓库(在Beanstalk上设置全新的仓库,如果这很重要)。 我的本地仓库有一些分支和标签,我想保留我的所有历史记录。 看起来我基本上只需要执行git push,但只上传master分支。 如何推送所有内容,以便在遥控器上获得我当地仓库的完整副本?


要推送所有分支,请使用(将REMOTE替换为远程名称,例如"origin"):

1
2
git push REMOTE '*:*'
git push REMOTE --all

推送所有标签:

1
git push REMOTE --tags

最后,我认为您可以在一个命令中执行以下操作:

1
git push REMOTE --mirror

但是,除了--mirror之外,还会推送你的遥控器,所以这可能不是你想要的。


在像我这样的情况下,你获得了一个回购,现在正在将远程原点切换到另一个回购,一个新的空回购......

所以你有你的repo和里面的所有分支,但是你仍然需要检查那些git push --all命令的分支以实际推送它们。

你应该在推动之前执行此操作:

1
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done

其次是

1
git push --all


这是对我所处的情况更好的另一种看法。它解决了你有多个遥控器的问题,想要将远程source中的所有分支克隆到远程destination但不必事先检查一下。

(我在Daniel的解决方案中遇到的问题是,如果我之前已经检查过它,它将拒绝从source远程检出跟踪分支,即它在推送之前不会更新我的本地分支)

1
git push destination +refs/remotes/source/*:refs/heads/*

Note:
If you are not using direct CLI, you must escape the asterisks:

git push destination +refs/remotes/source/\*:refs/heads/\*

  • @mattalxndr

这会将远程source中的所有分支推送到destination中的头分支,可能会执行非快进推送。您仍然需要单独推送标签。


git-push的联机帮助页值得一读。结合这个网站,我在.git/config中写了以下内容:

1
2
3
4
5
[remote"origin"]
    url = …
    fetch = …
    push = :
    push = refs/tags/*

push = :表示"推送任何'匹配'分支(即已存在于远程存储库中并具有本地对应分支的分支)",而push = refs/tags/*表示"推送所有标记"。

所以现在我只需要运行git push来推送所有匹配的分支和所有标签。

是的,这不是OP想要的(所有分支都必须已经存在于远程端),但是对于那些在搜索"我如何在同一时间推送分支和标签"时发现这个问题的人可能会有所帮助时间"。


如果目的地为空,这是我找到的最简洁的方法。切换到空文件夹,然后:

1
2
3
# Note the period for cwd >>>>>>>>>>>>>>>>>>>>>>>> v
git clone --bare https://your-source-repo/repo.git .
git push --mirror https://your-destination-repo/repo.git

适当地用https://...代替file:///your/repo等。


在我的情况下,有用的是什么。

1
git push origin --all


镜像存储库

创建存储库的裸克隆。

1
git clone --bare https://github.com/exampleuser/old-repository.git

镜像推送到新存储库。

1
2
cd old-repository.git
git push --mirror https://github.com/exampleuser/new-repository.git

删除您在步骤1中创建的临时本地存储库。

1
2
cd ..
rm -rf old-repository.git

镜像包含Git Large File Storage对象的存储库

创建存储库的裸克隆。将示例用户名替换为拥有存储库的个人或组织的名称,并将示例存储库名称替换为您要复制的存储库的名称。

1
git clone --bare https://github.com/exampleuser/old-repository.git

导航到刚刚克隆的存储库。

1
cd old-repository.git

拉入存储库的Git Large File Storage对象。

1
git lfs fetch --all

镜像推送到新存储库。

1
git push --mirror https://github.com/exampleuser/new-repository.git

将存储库的Git Large File Storage对象推送到镜像。

1
git lfs push --all https://github.com/exampleuser/new-repository.git

删除您在步骤1中创建的临时本地存储库。

1
2
cd ..
rm -rf old-repository.git

以上说明来自Github帮助:https://help.github.com/articles/duplicating-a-repository/


我发现上面的答案仍然有一些不清楚的东西,这会误导用户。首先,确定git push new_origin --allgit push new_origin --mirror不能复制所有原始分支,它只是将您当地存在的分支复制到new_origin。

以下是我测试的两种有用的方法:

1,复制克隆裸仓库。git clone --bare origin_url,然后输入文件夹,然后输入git push new_origin_url --mirror。通过这种方式,你也可以使用git clone --mirror origin_url--bare--mirror都会下载一个裸仓库,不包括工作区。请参考这个

2,如果您使用git clone进行git repo,这意味着您有裸仓库和git工作区,则可以使用git remote add new_origin new_origin_url,然后使用git push new_origin +refs/remotes/origin/\*:refs/heads/\*,然后使用git push new_origin --tags

通过这种方式,你将得到一个额外的头部分支,这是没有意义的。


推送分支和标签(但不是遥控器):

1
git push origin 'refs/tags/*' 'refs/heads/*'

这相当于组合git push--tags--all选项,git似乎不允许。


根据@Daniel回答,我做了:

1
2
3
4
for remote in \`git branch | grep -v master\`
do
    git push -u origin $remote
done


我发现这些似乎都不适合我。随意将其烧死,但由于某种原因无法让其他选项正常工作。

预期的结果是一个"克隆"到另一个远程(即从Github到另一个提供者)的repo:

  • 所有分支都在新的远程上创建
  • 所有分支历史记录都在新远程上创建

    • (我试过的每个解决方案都错过了这个)
  • 所有标签都在新的遥控器上创建
  • 来源移动(给定)
  • 非破坏性的(暂停--mirror选项)

我看到的主要问题是所有远程分支都没有在新的远程中重新创建。如果命令执行了,则新远程控制器没有分支历史记录(即,执行git checkout branch; git log不会显示预期的分支提交)。

我注意到git checkout -b branchnamegit checkout branchname不同(后者是我需要的)。我注意到git checkout --track branchname似乎没有拉动分支历史记录。

我的解决方案(基于PowerShell):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Function Git-FetchRemoteBranches {
$originalbranch = (git symbolic-ref HEAD).split("/")[-1]

Foreach ($entry in (git branch -r)) {

If ($entry -like"*->*") {
  $branch = $entry.split("->")[2].split("/")[1]
}
  else {$branch = $entry.split("/")[1]}

Write-Host"--Trying git checkout" -NoNewline
Write-Host"$branch" -Foreground Yellow

git checkout $branch

Remove-Variable branch -Force

""}

#Switch back to original branch, if needed
If ( ((git symbolic-ref HEAD).split("/")[-1]) -ne $originalbranch) {
"Switching back to original branch"
git checkout $originalbranch
Remove-Variable originalbranch -Force
}
}

git clone http://remoterepo
cd remoterepo
Git-FetchRemoteBranches
git remote add newremote
git push newremote --all
git push newremote --tags #Not sure if neeeded, but added for good measure