记一次使用git reset、git push --force的场景

文章讲述了如何在Gitee上合并两个仓库,包括将A仓库的主分支合并到B仓库,以及处理因合并导致的文件误删问题。在合并过程中,需要先将各分支合并到主分支,然后通过gitfetch和gitmerge操作将仓库合并。当发生误删文件并已push的情况,可以通过gitreset--soft和gitrestore等命令进行回滚。最后,文章介绍了如何在本地测试合并并推送到远程仓库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景

最近在整理个人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也是一样的操作):

  1. 拉取远程仓库到本地,并切换到主分支:

    # 拉取
    git clone <b_url>
    # 切换到主分支
    git checkout master
    
  2. 将其它分支合并到主分支,例如有个dev的分支要合并到主分支

    # 将dev分支合并到主分支
    git merge dev
    
  3. 回车后,需要输入合并的message,键入insert键可以进行输入信息,键入esc结束输入。再敲入:wq后回车,表示保持并退出,合并成功。

  4. 如果还有其它分支重复第二步操作即可。

  5. 合并完了,把更改同步到远端。

    git push
    

插曲,误删文件并commit 、push怎么办

如果没有误删问题,这里可以跳过

笔者的B仓库还有一个deploy的分支,这个分支创建的时候来源是主分支,但它是用来部署到服务器的,就把一些说明文档之类的都删除了,并且git记录了删除的操作。当时提交的记录也不规范,没有强调删了文件,哎呀。

将它合并到主分支后,没认真看,就直接推送到gitee上了。当打开gitee,发现怎么没了readme.md。回头看git日志:

git log

发现主分支把deploy分支的删除文档类文件的操作也同步过来了,赶紧在本地仓库回滚:

  1. 将merge过来的删除文件的操作,从本地仓库(git commit的地方)回退到暂存区(git add的地方):

    git reset --soft HEAD^
    

    执行以下命令查看暂存区状态,可以看到delete的操作回退到暂存区里了(此时工作区、暂存区的版本是一样的,都是删了文件的,而本地仓库里的已经回退到没删除前的版本)

    git status
    
  2. 把暂存区里的版本撤销,将删除文件操作从暂存区回退到工作区(暂存区的版本不撤销的话,工作区会以暂存区版本为参照基准,否则没办法在第3步将有原始文件的版本覆盖本地)

    git restore --staged .
    

    查看工作区状态,会发现delete操作只存在于工作区了,暂存区内容为空。

    git status
    
  3. 删除了文件的版本已经从完全撤销了,最新的版本是没有删除文件的版本,将最新版本的内容覆盖工作区,文件就回到工作区了:

    git restore .
    
  4. 以上步骤只是操作本地的仓库,还要把回滚的操作同步到远程仓库,让远程仓库也恢复该文件:

    # 因为要推送的版本比远程仓库的版本旧,所以要强推
    git push --force
    

将A、B仓库进行合并

合并前准备:

  • 在A仓库主分支中,创建一个a_code的文件夹,并将所有代码文件转移到该目录下(隐藏的.git文件夹不要移),然后修改同步到远端。该a_code目录用来合并到B仓库中,避免A和B的代码会混一块。

合并:

  1. 先克隆B仓库到本地,并切换到B仓库目录下:

    git clone [b_url]
    
  2. 在本地的B仓库中,添加A远程仓库地址作为B仓库的远程仓库之一:

    git remote add a_origin [a_url]
    
  3. 将A仓库的内容,拉取到B的本地仓库中缓存起来,此时A已经被认为是B的一部分了:

    git fetch a_origin
    
  4. 在B仓库初始化一个新分支,并以A仓库的master主分支为来源(上一步把A并入B的本地仓库了):

    # 相当于把A仓库的主分支嫁接到B仓库的新分支上
    git checkout -b for_a_branch a_origin/master
    
  5. 检查有哪些分支:

    git branch
    # master for_a_branch
    
  6. 为了稳妥,在新创建的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
    
  7. 合并成功后,切回master主分支,把for_a_branch分支的代码合并过来:

    git checkout master
    git merge for_a_branch
    
  8. 最后,把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
    
### 执行 `git reset --hard` 后进行推送 当执行了 `git reset --hard` 操作之后,本地分支的历史录会被重置到指定的提交版本,并且工作区也会恢复成该次提交时的样子。如果此时尝试直接推送到远程仓库,则可能会遇到拒绝推送的情况,因为这相当于试图覆盖远程历史。 为了成功推送更改后的状态至远程库,在强制推送之前应该先确保理解此操作的影响范围以及潜在风险。以下是具体的操作方法: #### 方法一:使用 `--force-with-lease` 推荐采用带有保护机制的安全方式来实现强制推送——即通过参数 `--force-with-lease` 来完成。这种方式可以在一定程度上防止误删他人已经更新的内容。 ```bash $ git push origin HEAD --force-with-lease ``` 这条命令的作用是在推送前检查目标分支是否有新的改动;如果有新改动而本地又丢失这些最新变化的话,那么此次推送将会失败从而避免意外删除其他开发者的贡献[^1]。 #### 方法二:传统意义上的强推(不推荐) 如果不考虑上述安全措施,也可以选择更为激进的方式来进行强行推送: ```bash $ git push origin HEAD --force ``` 请注意这种方法存在较大风险,因为它不会做任何额外验证就直接替换掉远端的历史录,可能导致团队协作中的数据丢失等问题[^2]。 无论采取哪种方式进行推送,都应当提前通知项目成员并确认这样做是必要的,以免影响他人的工作进展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值