本地分支领先远程分支,应该怎么正确去操作?要先 pull 还是直接 push --force?

2022-08-09 10:34:33 +08:00
 magic3584

由于昨天码云宕机,今天要提交代码。

刚才进行了如下操作:

  1. 如果直接 pull merge 的话提示没有冲突
  2. 使用 pull --rebase 以后有冲突,但是发现前两天的本地提交都没了。。。这种时候还能找回吗?

这两天遇到好几个非正常的 git 问题,都蒙了

7423 次点击
所在节点    git
84 条回复
msg7086
2022-08-10 00:32:13 +08:00
本地提交你用 git log 看? git log 又看不了。
pull rebase 是正常操作,pull merge 才是作大死。上面甚至有个建议日常作死的大佬我也是服气。
如果你实在想要锻炼自己去用这扭曲的命令行,那也最好先装个 GUI ,像这样不知所措的情况至少 GUI 能正确显示仓库当前的状态。
msg7086
2022-08-10 00:38:16 +08:00
@dfkjgklfdjg merge 可以把不正确的仓库改动隐藏在 merge commit 里。

比如你把 master 合并到 feature 上的时候产生了冲突,一顿解决以后合并成功了,然后过几天你把 feature 合并回 master ,结果 master 上某些功能不见了。然而你回溯回去却根本不知道是哪里出了问题。因为 merge commit 里可能会包含任何更改,不仅仅是 master 的更改,也可能是 master 覆盖 feature 后又被手动改回来的更改,甚至还可能包含既不在 master 也不在 feature 上的更改。因为 merge commit 本身就非常大,不可能单独检查,这种操作就等于是在代码提交历史里埋炸弹。

或者换句话说,这种 merge 就相当于把 feature 和 master 的提交揉在一起。不出事我才觉得奇怪。
FrankHB
2022-08-10 02:25:38 +08:00
@msg7086 这种 merge 出问题一般不见得那么麻烦,因为正常人都是遇到很少的 conflict 马上能处理完才会去耐心直接在 merge commit 上改(否则改了一半又有人提交就犯二了),而且 commit 本身不见得就很大。只是做了任何不能自动解决的操作都应该在 commit message 里说清楚。这样真有问题,大不了直接拎过 parents 手动重现。其实效果就是相当于把之前某个 parent 的最近的 commit 给 squash 上来了,如果改动直观到是个人就能看懂就无所谓,反正这种 merge 本来就得人工验证而不可能全自动化。反过来,有时候能自动解决的反而可能是错的,这是更坑的炸弹。
要是真是遇上脑子不大正常的,那就得拖过来教育扣工时了。
msg7086
2022-08-10 02:32:41 +08:00
@FrankHB 就怕有人心大直接在 merge conflict 上瞎基尔改,改完一交,神不知鬼不觉。
squash 完如果有 PR code review 的话倒还好,做个 diff 至少能看到改了点啥,但是像楼主的 team 这样愉快地打算 push -f 的就……
FrankHB
2022-08-10 02:47:04 +08:00
@msg7086 原则上像样的项目所有有实质改动的 commit 都最好走 pr 有别人 review ,再缺人那也得至少涵盖涉及不同 owner 的多个 branch 的 merge ,否则一旦出问题,锅就只能是 merge 的人背了,那就有点……活该了。
横竖都是一个人的项目锅都会自己背(虽说不该有并发提交的冲突),不过这种时候一旦吃亏就很容易长记性。
至于没搞清在干什么就敢 push -f (或者说,就敢允许非仓库配置管理员 push -f ),那是整个 team 在另一个次元意义上的活该(尤其是掉 commit )了。
bthulu
2022-08-10 08:12:43 +08:00
为啥不用 push --force? 我经常这样用一点问题也没有.
lovelylain
2022-08-10 08:23:03 +08:00
@han777 你是认真的吗?
@magic3584 去学下 pull push rebase checkout log diff 这几个命令吧,有冲突解决好冲突,master 分支不要 push -f ,开发分支可以在 rebase master 之后 push -f 使提交好看。针对你的问题,merge 是把远程当前状态合并到本地当前状态,而 rebase 是在远程当前状态上一条条写本地新提交,所以出冲突的概率比较大,可以两个方法都用,然后 git diff 检查冲突解决得是否 OK 。
lovelylain
2022-08-10 08:30:22 +08:00
@bthulu 你一个人开发用 push -f 无所谓,但是多人共同开发,对公共分支 push -f 就可能影响别人,所以最好是主干分支禁止 push ,开发分支在开发阶段要追新就 merge master ,开发好以后要合并代码 rebase master 再 push -f ,然后提一个开发分支到 master 分支的合并请求。
jeesk
2022-08-10 08:55:38 +08:00
本地有提交 先 git rebase , 合并远程代码。 再 push 就行了。
qwerthhusn
2022-08-10 09:01:34 +08:00
一个 force push 可能会搞挂整个团队,所以不要给普通开发人员开放 force push 权限
dfkjgklfdjg
2022-08-10 09:02:20 +08:00
@msg7086 #62 ,个人感觉这种坑即使使用了 rebase 依旧没办法避免啊?也没有在 message 里面说明改动情况吗?

这种问题不应该从提交、分工这边就把所有隐患都处理掉吗,特别是谁都有权限操作 master 的时候。
liuky
2022-08-10 09:13:12 +08:00
我都是先把本地 dev 分支更新到最新 develop pull
再 rebase develop --> feature_xxx 个人功能分支
再 merge feature_xxx --> develop
最后 push develop
pepesii
2022-08-10 09:22:01 +08:00
rebase 的时候解决冲突就行了
tairan2006
2022-08-10 09:33:22 +08:00
你这种情况还是 pull 完了 merge ,然后再 push 吧。
YouRTBUG
2022-08-10 09:37:23 +08:00
你就不能对下 commit id? 钓鱼?
wcp1231
2022-08-10 09:46:13 +08:00
「本地分支领先远程分支」这个不是很正常的情况吗?不知道是不是描述不准确。

如果本地分支和远程分支在一条线上
- 本地分支领先远程分支:那说明这个分支只有你的修改,完全不会有冲突,git push 就能把本地代码推到远程;
- 远程分支领先本地分支,那说明这个分支只有别人的修改,完全不会有冲突,git pull 就能把远程分支的改动拉到本地

如果本地分支和原创分支分叉,那说明你和其他人都进行了修改,并且别人已经把改动推到了远程。
- git pull 是把本地分支和远程分支做 merge
- git pull --rebase 是把本地分支 rebase 到远程分支

也有其他的处理方式,不过如果有冲突那不管哪种方式都是要处理冲突的
msg7086
2022-08-10 09:56:14 +08:00
@dfkjgklfdjg rebase 以后 master 的变更和个人的变更是分开的,不会像 merge commit 那样既有 master 的变更,又有个人偷偷塞进去的变更。
wangyzj
2022-08-10 10:33:33 +08:00
我感觉码云那边在 bare 里面做个 gc 就好了
至于本地可以复制一份,然后 rebase 解冲突
如果缺少的话就 cherry-pick
丢东西可能性不大

要是人少,可以线下协同,force 也不是不行
han777
2022-08-10 10:41:50 +08:00
@jobmailcn 我是认真的。当我是一个刚学会 git 几天的*新手*时,搞不清提交、冲突、变基这些复杂概念,也不知道怎么解决冲突时,显然,复制粘贴是一个简单又易行的解决方案。
Edsie
2022-08-10 10:59:41 +08:00
建议使用 rebase -i 这样就能知道哪些 commit 会被 rebase
养成良好习惯😃

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/871607

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX