git 常见问题和解决方法

先介绍一下基本知识点,如已了解,直接跳到第五点

一、git merge 与 git rebase的区别

1.基于远程分支"origin",创建一个叫"mywork"的分支
在这里插入图片描述

git merge

在这里,你可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并; 结果看起来就像一个新的"合并的提交"(merge commit):

在这里插入图片描述

git rebase

在这里,你可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并; 结果看起来就像一个新的"合并的提交"(merge commit):

$ git checkout mywork
$ git rebase origin

这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。

在这里插入图片描述
当’mywork’分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除. (请查看 git gc)

在这里插入图片描述
现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:

在这里插入图片描述
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
解决冲突后执行一下命令

$ git add .
 git rebase --continue

这样git会继续应用(apply)余下的补丁。

在任何时候,你可以用–abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。

$ git rebase --abort

(merge 冲突解决后 add -->commit 不用(commit -m )

merge:
优点:比较容易理解
缺点:历史可能混乱
适合的合作模式:大部分情况合作者相互熟悉,

rebase:
优点:可以按作者清所区分commit
缺点:时间顺序会板打乱现解起来较为复杂
适合的合作模式:大企业多个团队,互相交流较少,各自集中开发

总结
git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式

git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的patch,并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit点,可以保持整个分支树的完美线性

另外值得一提的是,当我们开发一个功能时,可能会在本地有无数次commit,而你实际上在你的master分支上只想显示每一个功能测试完成后的一次完整提交记录就好了,其他的提交记录并不想将来全部保留在你的master分支上,那么rebase将会是一个好的选择,他可以在rebase时将本地多次的commit合并成一个commit,还可以修改commit的描述等

如果你想要你的分支树呈现简洁,不罗嗦,线性的commit记录,那就采用rebase

否则,就用merge吧

二、git pull和git commit的顺序问题

1.在本地修改与远程代码无冲突的情况下,优先使用:pull->commit->push
2.在本地修改与远程代码有冲突的情况下,优先使用:commit->pull->push

那么我们怎么去确定是否有冲突呢?

一般我们在合作开发一个项目的过程中,都会有分工,有时会两个人同时修改一个类,有时整个类都是你自己在开发。
如果都是自己在开发的类,当然优先使用pull->commit->push,为什么我更倾向这种方式呢,因为这样会减少Git没有必要的merge。

如果有冲突的情况下,先pull了会出现什么问题呢?

如果你的判断失误,在本地修改与远程代码有冲突的情况下,先执行了git-pull,即使是这样也不用担心,git会给你一个错误提示,这时候你再去执行commit->pull->push也是没有问题的。

如果是idea 直接pull 会自动保存stash 在合并解决冲突。commit后还是一条笔直的记录

三、Stash 操作

stash命令可用于临时保存和回复修改,可跨分支。

(1)git stash save "save message"  : 执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别。

(2)git stash list  :查看stash了哪些存储

(3)git stash show :显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

(4)git stash show -p : 显示第一个存储的改动,如果想显示其他存存储,命令:git stash show  stash@{$num}  -p ,比如第二个:git stash show  stash@{1}  -p

(5)git stash apply :应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1} 

(6)git stash pop :命令恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下,默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

(7)git stash drop stash@{$num} :丢弃stash@{$num}存储,从列表中删除这个存储

(8)git stash clear :删除所有缓存的stash

四、 Rebase 合并多个commit提交

1、git log 查看提交历史记录
2、git 压缩 git rebase -i HEAD~6 or git rebase -i 10b73908 5260c17470
修改第2~6行的第一个单词 pick 为 squash or s,然后 输入:wq or x 保存退出。
git rebase –i ,这里的 “-i” 是指交互模式。就是说你可以干预rebase这个事务的过程,包括设置commit message,暂停commit等等。
git rebase -i [commit_log] 这个id 之后 前开后闭
pick 的意思是要执行这个 commit
squash 的意思是这个 commit 会被合并到前一个 commit
git 会压缩提交历史,若有冲突,需要进行修改,修改的时候保留最新的历史记录,修改完之后输入以下命令:
3、git add .
4、git rebase —continue
5、若想退出放弃此次压缩,执行命令:
git rebase --abort
若无冲突 or 冲突已 fix,则会出现一个 commit message 编辑页面,修改 commit message ,然后 输入:wq or x 保存退出。

·  pick:保留该commit(缩写:p)
·  reword:保留该commit,但我需要修改该commit的注释(缩写:r)
·  edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
·  squash:将该commit和前一个commit合并(缩写:s)
·  fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
·  exec:执行shell命令(缩写:x)
·  drop:我要丢弃该commit(缩写:d)

五、 Rebase 修改commit提交信息

1、git commit —amend 修改最后一次注释

git commit --amend

出现有注释的界面(你的注释应该显示在第一行), 输入i进入修改模式,修改好注释后,按Esc键 退出编辑模式,输入:wq保存并退出。ok,修改完成。

2、修改之前的某次注释

输入:
git rebase -i HEAD~2
最后的数字2指的是显示到倒数第几次 比如这个输入的2就会显示倒数的两次注释(最上面两行)

你想修改哪条注释 就把哪条注释前面的pick换成edit。方法就是上面说的编辑方式:i---编辑,把pick换成edit---Esc---:wq.

然后:(接下来的步骤Terminal会提示)
git commit --amend

修改注释,保存并退出后,输入:
git rebase --continue


如果把pick换成r 就不会有后续的 git commit --amend git rebase --continue 操作

其实这个原理我的理解就是先版本回退到你想修改的某次版本,然后修改当前的commit注释,然后再回到本地最新的版本

修改多次的注释其实步骤和上面的一样,不同点在于:

同上
你可以将多个想修改的commit注释前面的pick换成edit
依次修改你的注释(顺序是从旧到新),Terminal基本都会提示你接下来的操作,每修改一个注释都要重复上面的3和4步,直到修改完你所选择的所有注释
已经将代码push到远程仓库
首先,你把最新的版本从远程仓库先pull下来,修改的方法都如上,最后修改完成后,强制push到远程仓库:
git push --force origin master
注:很重要的一点是,你最好保证在你强制push之前没有人提交代码,如果在你push之前有人提交了新的代码到远程仓库,然后你又强制push,那么会被你的强制更新覆盖!!!

最后,可以检查一下远程的提交记录~~

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐