记一次使用git reset、git push --force的场景
如何合并两个代码不同的仓库,例如将前端仓库合并到后端仓库,可以怎么操作。如果误删文件怎么通过回滚来恢复文件。另外还有一些常用的分支操作。
场景
最近在整理个人gitee一些旧的分散仓库:
-
一个典型的场景是,多年前自己写了个全栈玩具项目,前后端分在了两个仓库中,现在希望将它们合并到一个仓库中管理。
-
期间,对某一个仓库进行分支合并时,因为被合并的来源分支删除过文件,导致合并到主分支后,主分支的文件也被删除了,当时没发现,还推到gitee上了。需要先本地回滚再强推。
吐槽一下:百度合并两个仓库的方法时,有被网上的复制粘贴恶心到,起码把自己的实践经历加进来吧,直接复制粘贴,还有漏步骤的🤮。
准备
经过网上检索答案,例如有A、B两个不同的仓库:
将A仓库的主分支代码,拉取到B仓库的一个新建分支for_a里,然后将for_a分支合并到B的主分支,完成!
说白了就是:将A仓库的一个(主)分支,merge到B仓库的一个(主)分支里。
大体步骤:
-
将A仓库的所有分支都先合并汇总到主分支,B仓库也是,如果分支简单,这一步忽略。
-
在B仓库添加A仓库的远程地址,作为自己的远程仓库来源之一,然后将A远程仓库fecth下来。这样A就加入到B的本地仓库中了。
git fecth 只把代码拉到本地仓库。例如这里只是把A仓库fetch到了B的本地仓库,也还没真正和B建立关联,所以工作区没办法看出fetch了。
git pull 会把代码拉到本地仓库和工作区,具体可百度。
-
在B仓库开辟一个新分支,先叫for_a,但初始化的代码来自A仓库主分支(上面fetch整个A仓库到B的本地仓库了)。这样A仓库的主分支以for_a分支的形式"嫁接"到了B仓库上。
-
将for_a分支与B仓库的主分支合并,A仓库主分支的代码还有提交记录都会并入到B仓库的主分支,成功!
开始
对A、B仓库各自进行主分支合并
目的是保证最终合并后,合并结果包含A和B各自的全量修改,并且后续合并其它分支可避免出现冲突。
合并步骤,以B为例(A也是一样的操作):
-
拉取远程仓库到本地,并切换到主分支:
# 拉取 git clone <b_url> # 切换到主分支 git checkout master
-
将其它分支合并到主分支,例如有个dev的分支要合并到主分支
# 将dev分支合并到主分支 git merge dev
-
回车后,需要输入合并的message,键入insert键可以进行输入信息,键入esc结束输入。再敲入
:wq
后回车,表示保持并退出,合并成功。 -
如果还有其它分支重复第二步操作即可。
-
合并完了,把更改同步到远端。
git push
插曲,误删文件并commit 、push怎么办
如果没有误删问题,这里可以跳过
笔者的B仓库还有一个deploy的分支,这个分支创建的时候来源是主分支,但它是用来部署到服务器的,就把一些说明文档之类的都删除了,并且git记录了删除的操作。当时提交的记录也不规范,没有强调删了文件,哎呀。
将它合并到主分支后,没认真看,就直接推送到gitee上了。当打开gitee,发现怎么没了readme.md。回头看git日志:
git log
发现主分支把deploy分支的删除文档类文件的操作也同步过来了,赶紧在本地仓库回滚:
-
将merge过来的删除文件的操作,从本地仓库(
git commit
的地方)回退到暂存区(git add
的地方):git reset --soft HEAD^
执行以下命令查看暂存区状态,可以看到delete的操作回退到暂存区里了(此时工作区、暂存区的版本是一样的,都是删了文件的,而本地仓库里的已经回退到没删除前的版本)
git status
-
把暂存区里的版本撤销,将删除文件操作从暂存区回退到工作区(暂存区的版本不撤销的话,工作区会以暂存区版本为参照基准,否则没办法在第3步将有原始文件的版本覆盖本地)
git restore --staged .
查看工作区状态,会发现delete操作只存在于工作区了,暂存区内容为空。
git status
-
删除了文件的版本已经从完全撤销了,最新的版本是没有删除文件的版本,将最新版本的内容覆盖工作区,文件就回到工作区了:
git restore .
-
以上步骤只是操作本地的仓库,还要把回滚的操作同步到远程仓库,让远程仓库也恢复该文件:
# 因为要推送的版本比远程仓库的版本旧,所以要强推 git push --force
将A、B仓库进行合并
合并前准备:
- 在A仓库主分支中,创建一个
a_code
的文件夹,并将所有代码文件转移到该目录下(隐藏的.git
文件夹不要移),然后修改同步到远端。该a_code
目录用来合并到B仓库中,避免A和B的代码会混一块。
合并:
-
先克隆B仓库到本地,并切换到B仓库目录下:
git clone [b_url]
-
在本地的B仓库中,添加A远程仓库地址作为B仓库的远程仓库之一:
git remote add a_origin [a_url]
-
将A仓库的内容,拉取到B的本地仓库中缓存起来,此时A已经被认为是B的一部分了:
git fetch a_origin
-
在B仓库初始化一个新分支,并以A仓库的master主分支为来源(上一步把A并入B的本地仓库了):
# 相当于把A仓库的主分支嫁接到B仓库的新分支上 git checkout -b for_a_branch a_origin/master
-
检查有哪些分支:
git branch # master for_a_branch
-
为了稳妥,在新创建的for_a_branch分支试一下合并分支代码:
执行执行合并分支命令后,需要在vi命令行输入合并的message。可参考上面:合并A、B各自主分支那一步。
# 确保切换到for_a_branch git checkout for_a_branch # 在for_a_branch分支将master分支的代码合并过来 git merge master --allow-unrelated-histories
-
合并成功后,切回master主分支,把for_a_branch分支的代码合并过来:
git checkout master git merge for_a_branch
-
最后,把master分支的代码推送到远端即可,本地的for_a_branch分支无需推送,直接删除本地整个库,重新拉取远端的即可(前提是先看看远端推送成功没有)。
git push
到这里已经成功了!
其它git命令
-
如果当前工作区分支和要推送到的远程分支命名不一样,是无法推送的
# 将当前所在的master分支代码推送到远端的main分支上 git push <git_url> master:main
-
新建本地分支并推送到远端
# 创建本地新分支 git branch test # 切换到新分支 git checkout test # 将新分支推送到远端 git push -u <git_url> test
-
本地删除分支
# 切换到其它分支上,不能是要删除的分支 git checkout <other_branch> # 将test分支安全删除 git branch -d test # 将当前分支强制删除 git branch -D test
-
查看base操作历史
history
更多推荐
所有评论(0)