关于git merge,rebase合并的差别,以及*(no branch)的处理。

本文深入探讨Git中分支管理的两种主要合并策略:merge与rebase。详细讲解了它们的工作原理、应用场景及注意事项,包括如何处理冲突、保持历史线性及避免数据丢失。同时,介绍了*(nobranch)状态的含义及应对策略。

1.merge

        在上篇介绍分支的时候有简单的说了一下分支的创建和合并,当时合并就是写的merge,这是依据两个不同分支的最后一次提交的commit对象c5,c7和两个分支的交叉点的commit对象c3进行一次简单的三方合并,终于得到一个新的commit来作为终于的提交commit对象c8,指针指向c8,并且c4,c5,c6,c7是存在于本地仓库的历史版本号,我们能够通过日志查看找到这两个commit,相同也能够恢复到这两个版本号。也就是以下这个图:

        上图是将test分支合并到master分支,然后我们来实现一次,假如如今已经到了c3,我新建一个分支test,然后先用master分支改动我的test.txt文件并提交反复两次,得到c4和c5,然后再切换到test分支相同对test.txt改动并提交两次,得到c6和c7,然后切换到master分支运行合并操作,这时会提示有冲突,最后我们解决冲突了再提交:

冲突:

日志:

2.rebase

        rebase称为衍合,这是个什么概念呢,例如以下图,当我们把test衍合到master的时候,是将c5,和c6中发生的变化打成补丁然后再c8的基础上做改动的,假设这个时候遇到冲突,就必需要我们自己决绝好冲突之后,加入到暂存区然后再继续合并,c5的变化补丁在c8上发生变化之后得到c5'这个commit对象,而c6的变化补丁再在c5'上改动得到c6',然后指针指向c6',这个过程我们称之为衍合,并且这个过程都是在一个*(no branch)分支上做的,这个后面会说到。并且有一个要注意的地方,假设git运行git gc或者我们手动运行git gc,那么c5和c6就不再存在于我们的本地仓库,我们就再也找不回这两个commit了,这个过程就是一个线性的过程,在test运行完之后,再在test的基础上运行master的操作。以上就是rebase和merge的差别所在。

        和merge一样,我们实际来做一次,如果如今我们已经在c4了,这时候创建test分支,全部改动操作和merge一样,然后我们用rebase这样的方式来把test衍合到master上:

冲突:

日志:

3.*(no branch)

        在运行命令git branch查看分支的时候,假设出现*(no branch),则表示不在不论什么分支上进行工作。出现这样的情况我也是在几次不经意之间,用git checkou回溯版本号的时候,用git pull或者merge和rebase的时候会出现*(no branch)。眼下我在rebase的时候都是在*(no branch)上进行的,当衍合完毕后自己主动切到master上,我认为这是个正常现象,可是其它几种方式就不正常了,详细原因我也不是非常清楚。

        因为*(no branch)表示不在不论什么分支上进行,而有时我们不知道自己是在*(no branch)上进行操作的,并且可能我们已经进行非常久的开发工作了,已经提交好几个版本号的代码了,突然运行git branch发如今*(no branch)上,是不是一件非常恐怖的事啊。

        当然经过提交的版本号数据都会以快照的方式被记录在commit对象存在.git文件夹的objects子文件夹里,那么当我们发现是在*(no branch)时应该怎么解决呢。有两种情况。

        第一种情况是我们还没离开*(no branch),这个时候,我们能够运行git checkout -b mybranch命令,这个时候会创建新分支mybranch,并将*(no branch)里面的数据都checkout到mybranch分支上,然后我们再在mybranch上开发,终于合并到master上。

        另外一种情况就不乐观了,我们已经离开*(no branch)了,然后发现用git log都找不到之前的提交了,当然了,在*(no branch)上提交的,在别的分支上怎么找的到在它上面提交的数据呢。只是或许还有救,假设git还没有运行git gc,那么我们能够通过运行git reflog找到在*(no branch)上提交的数据,然后依据找到的commit的id来恢复该数据,这也是最后唯一的希望了,假设git已经运行了git gc或者你手贱自己运行了git gc,那么就真的不能在一起愉快的玩耍了。

        所以在运行过git checkout恢复过曾经的数据或者是做过合并分支的操作,那么不要吝啬你们的git branch,敲这个命令又不要钱,却能让你之后的提交高枕无忧。

4.总结

        merge的合并是三方合并,并且历史版本号都在本地方库中,可是却比較繁琐,并且开发的过程是个网状结构,假设创建的分支比較多,进行的merge也比較多,那么就算我们在纸上画它的提交历史都会画的手疼,可是rebase就不一样,它是依据另外一个分支的改动内容进行打补丁然后在前一个分支的最后提交上进行改动,并且将另外一个分支的提交历史删除,这样就是一个线性的过程,非常清晰。所以在推送到远程仓库之前尽量多用rebase来衍合分支,可是假设将一个commit推送到远程仓库之后,就不要再对它进行衍合操作了,由于这种话,它非常可能在你的某次衍合过程中被删除,那么再推送到远程仓库就会造成非常大的损失。切记,rebase虽好可不要贪杯。rebase除了 --continue外,还有 --skip 和 --abort 操作,其中skip会忽略自己的提交,而更新为远程仓库版本;abort会放弃本次合并操作,回到rebase之前的状态。

转载于:https://www.cnblogs.com/ZJOE80/p/10543241.html

### Git MergeGit ReBase的区别及使用场景 #### 区别 1. **提交历史的处理方式** - `git merge` 创建一个新的合并提交,将两个分支的更改合并到一个新的提交中。这种方式会保留分支的历史记录,清晰地展示分支的合并过程[^4]。 - `git rebase` 通过移动分支指针来实现合并,它将当前分支上的提交按照顺序逐个应用到目标分支上,并将目标分支指针移动到最新的提交上。这种方式使得提交历史更加线性,但会丢失分支结构信息[^4]。 2. **冲突解决** - 在 `git merge` 中,如果发生冲突,Git 会在创建合并提交时提示用户解决冲突。解决后继续完成合并操作[^3]。 - 在 `git rebase` 中,冲突可能发生在每个提交的重放过程中。因此,`rebase` 的冲突解决过程通常更复杂,需要逐个解决每个提交中的冲突[^4]。 3. **历史记录的可读性** - `git merge` 的历史记录包含分支的合并点,适合用于需要保留分支开发过程的场景。 - `git rebase` 的历史记录更加线性,适合用于希望保持代码库整洁、避免过多分支结构的场景。 #### 使用场景 1. **Git Merge 的适用场景** - 当希望保留完整的分支历史,以及显示出分支合并的细节时,选择 `git merge`[^2]。 - 在团队协作中,如果需要清晰地看到不同功能分支的开发过程和合并点,`git merge` 是更好的选择[^4]。 2. **Git Rebase 的适用场景** - 如果希望保持更线性、整洁的提交历史,并且能够容忍更复杂的冲突解决过程,选择 `git rebase`[^2]。 - 在开发过程中,为了保持提交历史的整洁和线性,经常使用 `rebase` 来更新本地分支到最新状态。 - 在个人开发或小型团队中,当不需要保留分支结构时,`rebase` 可以提供更简洁的历史记录。 #### 示例代码 以下为 `git merge` 和 `git rebase` 的基本使用示例: ```bash # 使用 git merge 合并分支 git checkout main git merge feature-branch # 使用 git rebase 重写提交历史 git checkout feature-branch git rebase main ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值