git 远程仓库代码迁移

1、代码迁移

1.1 多分支迁移

在开发中不可避免的会从一个仓库将代码迁移到另一个仓库,简单的做法是将代码全部档下来,然后删除远程分支,重新指向远程新仓库的地址,这样需要有一段时间的代码停用空挡,也就是说这段时间是不允许任何人提交代码的,而且缺少一个缓冲区,一旦迁移完成,如果有开发人员没有没有同步继续向旧仓库提交代码,那向旧仓库提交的代码就很难同步到新仓库。
我们是否有什么办法可以保证管理人员能够同时处理新旧仓库的版本,给开发人员一个切换远程仓库的缓冲时间那?

  • 1、首先修改旧远程仓库的别名
>git remote
origin
>git remote rename origin origin-old (将旧仓库origin修改为origin-old)
查看修改后的别名
>git remote
origin-old
查看本地分支和远程分支的跟踪关系,发现它们依然指向同一条日志
>git branch -vv
* main f2eda30 [origin-old/main] ...
除了别名之外指向关系没有发生任何变化
>git branch -r -a
* main
  remotes/origin-old/HEAD -> origin-old/main
  remotes/origin-old/main

此时我们仅仅只是对远程仓库修改了别名的名字,它的对应关系没有任何改变,目的只是为新仓库腾出一个位置,如果不介意,可以不必进行此操作,现在我们提交合并代码不会受到任何影响。

  • 2、接下来创建新仓库的引用(别名)
>git remote add origin ssh://git@*.git
查看创建效果,此时已经有两个别名,它们分别对应新旧仓库
git remote -v
origin  ssh://git@*.git (fetch)
origin  ssh://git@*.git (push)
origin-old      ssh://git@*.git (fetch)
origin-old      ssh://git@*.git (push)

每个分支,其实就只是一个轻量级指针而已,分支就指向了提交历史中的某个commit 对象。而commit 对象指的是这个项目的所有代码在完成一次提交后生成的快照版本,所以每一个commit 对象都代表了项目的一个版本。
正是因为指针的轻量,因此在git中分支的来回切换速度是非常快的。

  • 3、一些原理性知识(可以不关注)

    • (1)我们的项目是怎样知道当前工作在哪个分支上的?

    在执行完git init后本文件夹下会生成一个.git文件,打开.git文件会看到有一些文件和文件夹,其中有一个HEAD文件,其实可以将其理解为一个特殊的指针,这个指针指向了我们当前的工作分支,此时指向的正式main分支更确切的说是main指针,因为分支即指针。

    ref: refs/heads/main
    
    • (2)分支指向的内容

    顺着HEAD的内容往下查找打开 refs/heads/main 文件

     f2eda30a356db1683aee683c0eea1f248980fd39
    

    这个字符串又是什么意思那?比对一下提交日志,发现正好是一次commit 对象(也就是一个代码快照)不仅如此观察refs/remotes/origin-old/HEAD与refs/remotes/origin-old/main发现origin-old/HEAD->origin-old/main->此commit 对象
    那是不是说远程分支和本地分支永远都指向同一个commit 对象那?当然不是,当本地分支有提交或远程分支有更新时或者本地分支在版本间游走的时候,本地分支与远程分支都不可能指向同一个commit 对象。但最终的是会指向同一条记录的即本地分支与远程分支完全同步的时候

    git log
    commit f2eda30a356db1683aee683c0eea1f248980fd39 (HEAD -> main, origin-old/main, origin-old/HEAD)
    
    • (3)、git是怎样处理默认远程分支的?

    我们提交代码的时候往往不去指定远程分支是哪一个(当然你也可以去指定),而是直接通过git fetchgit push等命令直接拉取或推送到远程分支,因此可以想到git一定是有一个地方帮我们维护了这样一个关系,或者说维护着本地分支指向某个远程分支的指针,这个文件就是config

    [core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
    [remote "origin-old"]
        url = ssh://git@*.git
        fetch = +refs/heads/*:refs/remotes/origin-old/*
    [branch "main"]
        remote = origin-old
        merge = refs/heads/main
    [remote "origin"]
        url = ssh://*.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    

    先不关心[core]中的内容。在本地分支[main]中我们看到有两条记录 remote 和 merge很显然,remote指向了远程仓库的别名也就是"origin-old"说明本地仓库与远程仓库的确建立了关联关系。可以通过git branch -avv命令查看本地分支、远程分支及他们的对应关系。
    我们查看一个本地多个分支指向同一个远程分支的例子,本地分支dev和main指向了同一个远程main分支

    [core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
    [remote "origin"]
        url = ssh://git@gxx.sundun.cn:226/shce/code/shce-web.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "main"]
        remote = origin
        merge = refs/heads/main
    [branch "dev"]
        remote = origin
        merge = refs/heads/main
    

    只要改变了本地分支的merge,远程分支是通过[remote]中的fetch进行维持指向的,这里没有写死而是通过后缀匹配的方式来维护链接关系,这样的好处是无论远程仓库有多少个分支都可以通过一个配置来匹配,而具体的分支名则维护在[branch]中,这样一来本地有多少个分支就有多少个[branch]而一个远程仓库无论有多少个分支都只有一个与其对应的[remote],这样的好处是可以尽可能的保持远程仓库配置的稳定。

  • 4、本地分支指向新的远程仓库的main分支

通过git branch -u 远程仓库别名/分支名 命令可以帮助切换分支,那么是不是说直接执行命令就大功搞成了?答案是对的,但在一定条件下又不完全对,有时在执行之前还要执行一条其他命令。

>git branch -u origin/main
error: the requested upstream branch 'origin/main' does not exist
hint:
hint: If you are planning on basing your work on an upstream
hint: branch that already exists at the remote, you may need to
hint: run "git fetch" to retrieve it.
hint:
hint: If you are planning to push out a new local branch that
hint: will track its remote counterpart, you may want to use
hint: "git push -u" to set the upstream config as you push.

直接执行报错,这是因为本地仓库只是建了远程新仓库的别名,但具体仓库中有它是不知道的因此首先执行同步。

同步前

>git branch -avv
* main                    f2eda30 [origin-old/main] ...
  remotes/origin-old/HEAD -> origin-old/main
  remotes/origin-old/main f2eda30 ...
>git fetch origin
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From ssh:*
 * [new branch]      main       -> origin/main

同步后

>git branch -avv
* main                    f2eda30 [origin-old/main] ...
  remotes/origin-old/HEAD -> origin-old/main
  remotes/origin-old/main f2eda30 ...
  remotes/origin/main     00c01ee Initial commit

同步后已经可以看到新仓库的分支

>git branch -u origin/main
Branch 'main' set up to track remote branch 'main' from 'origin'
>git branch -avv
* main                    f2eda30 [origin/main: ahead 80, behind 1] ...
  remotes/origin-old/HEAD -> origin-old/main
  remotes/origin-old/main f2eda30 ...
  remotes/origin/main     00c01ee Initial commit

此时分支切换成功。赶紧执行命令。

>git push
To ssh://gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'ssh://git@gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
E:\Workspace\Idea_shce\shce-master>git push -f 
Enumerating objects: 2555, done.
Counting objects: 100% (2555/2555), done.
Delta compression using up to 8 threads
Compressing objects: 100% (1306/1306), done.
Writing objects: 100% (2555/2555), 1.48 MiB | 9.01 MiB/s, done.
Total 2555 (delta 1101), reused 1321 (delta 508)
remote: Resolving deltas: 100% (1101/1101), done.
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To ssh://gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'ssh://git@gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git'

无论是同步还是温柔的推送还是强制推送不出意外都失败了。提示不能推送到一个受保护的分支。
既然保护了我们就给他解开保护 在gitlab 或 gitee 或 github上解开保护,别忘了操作完后开启保护。
"Settings" -> "Repository" -> Protected branches
此时执行强制提交已经可以提交成功。

>git push -f
Enumerating objects: 2555, done.
Counting objects: 100% (2555/2555), done.
Delta compression using up to 8 threads
Compressing objects: 100% (1306/1306), done.
Writing objects: 100% (2555/2555), 1.48 MiB | 7.72 MiB/s, done.
Total 2555 (delta 1101), reused 1321 (delta 508)
remote: Resolving deltas: 100% (1101/1101), done.
To ssh://gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git
 + 00c01ee...f2eda30 main -> main (forced update)

1.2 拉取或提交

先看一下结构好像并没有改变,其实背后的工作都已经完成,剩下的就是使用。

[remote "origin-old"]
	url = ssh://git@gxx.sundun.cn:226/shce/code/shce-master.git
	fetch = +refs/heads/*:refs/remotes/origin-old/*
[branch "main"]
	remote = origin-old
	merge = refs/heads/main
[remote "origin"]
	url = ssh://git@gxx.sundun.cn:226/pm-hb/jn-shce/code/shce-master.git
	fetch = +refs/heads/*:refs/remotes/origin/*

git branch -u origin-old/main切换到原仓库
git push提交代码
git fetch 同步远程分支到本地
git merge合并代码

git branch -u origin/main切换到新仓库
git push提交代码
git fetch 同步远程分支到本地
git merge合并代码

git remote rm 远程仓库别名 删除远程仓库别名

1.3 创建并切换本地及远程分支

git branch standard && git checkout standard && git push origin standard

2、总结

上面的叙述过去繁琐其实代码从一个仓库迁移到另一个仓库我们只需要按照下面这个步骤执行即可

  • git remote rename origin origin-old 修改别名
  • git remote add origin ssh://*.git 添加新的远程仓库
  • git fetch origin 同步远程仓库信息
  • git branch -u origin/main 切换到新的分支
  • git push origin HEAD:main -f 强制提交(如果报受保护的分支先去掉保护允许强制提交)
  • git branch standard && git checkout standard && git push origin standard 在当前版本的基础上创建新的分支并推送到远程仓库
  • 一下命令为具体业务,请根据自己情况自行百度。
  • git branch -m main main-old 修改本地分支名
  • git checkout main-old 切换到重命名的分支
  • git branch -u origin-old/dev dev 将本地分支dev与远程分支关联

最后的关系图

  dev                        ff154c1 [origin-old/dev: behind 1] 
  main                      ff154c1 [origin/main] 
* main-old                f64a17b [origin-old/main: behind 132] 
  standard                 ff154c1 [origin/standard] 
  remotes/origin-old/HEAD -> origin-old/main
  remotes/origin-old/dev  e3fab1c 
  remotes/origin-old/main ff154c1 
  remotes/origin/main     ff154c1 
  remotes/origin/standard ff154c1 

将来代码全部在新仓库上开发时可以删掉旧的分支。

注意这是最后的关系,在程序迁移期间一定不是这样的,需要站在最新版本的分支上去切换指向远程仓库的指针来拉取推送代码,因为要保持HEAD指针指向的工作区的代码一定是最新的。切不可通过checkout的方式去切换分支。

回答: 当出现"no such origin"的错误提示时,通常是因为本地仓库没有正确关联到远程仓库。解决这个问题的方法是重新关联远程仓库。根据引用\[1\]中的提示,可以使用以下命令来删除关联的远程库并重新关联自己的仓库: ``` git remote rm origin #删除关联的origin远程git remote add origin xxxxx #重新关联自己的仓库 ``` 另外,根据引用\[2\]中的提示,还可以使用以下步骤来迁移代码到新的仓库并关联远程仓库: ``` git remote rename origin origin-old #修改别名 git remote add origin ssh://*.git #添加新的远程仓库 git fetch origin #同步远程仓库信息 git branch -u origin/main #切换到新的分支 git push origin HEAD:main -f #强制提交 git branch standard && git checkout standard && git push origin standard #在当前版本的基础上创建新的分支并推送到远程仓库 ``` 最后,根据引用\[3\]中的提示,可以使用以下命令来查看本地分支、远程分支及它们的对应关系: ``` git branch -avv #查看本地分支、远程分支及他们的对应关系 ``` 希望以上信息能够帮助你解决问题。 #### 引用[.reference_title] - *1* [Git绑定远程仓库报错error: remote origin already exists.](https://blog.csdn.net/qq_52855464/article/details/126475334)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [git 远程仓库代码迁移](https://blog.csdn.net/qq_16494381/article/details/123715982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值