多人开发的正确工作流程 在dev1分支下我们开发一个新功能,并且在开发的时候分成3个stage提交(方便改bug),但是实际上我们最终只需要提交一个代表该新功能的commit到远端,并合入main分支,应该怎么做呢?
dev 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ➜ learn-git git:(dev1) git add . ➜ learn-git git:(dev1) ✗ git commit -m "feat: feature 1" [dev1 53 adc27] feat: feature 1 1 file changed, 2 insertions(+), 1 deletion(-) ➜ learn-git git:(dev1) git add . ➜ learn-git git:(dev1) ✗ git commit -m "feat: lunch time" [dev1 3874836 ] feat: lunch time 1 file changed, 2 insertions(+), 1 deletion(-) ➜ learn-git git:(dev1) ✗ git add . ➜ learn-git git:(dev1) ✗ git commit -m "fix: brunch time" [dev1 94 a90c2] fix: brunch time 1 file changed, 1 insertion(+), 1 deletion(-)
local cleanup 查看提交记录,找到对于该功能一共提交了多少次,这里是3次
1 ➜ learn-git git:(dev1) git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 commit 94 a90c28d614326dcbd3a4df2739c5775c60eb78 (HEAD -> dev1)Author : mmy <15224924822 @163 .com>Date : Sat May 18 12 :37 :41 2024 +0800 fix : brunch timecommit 38748366091 e3dbd30a1ce4ab995ece8671720adAuthor : mmy <15224924822 @163 .com>Date : Sat May 18 12 :37 :06 2024 +0800 feat : lunch timecommit 53 adc276bae51c26f0bc5c7ca503d017027fe1c4Author : mmy <15224924822 @163 .com>Date : Sat May 18 12 :36 :42 2024 +0800 feat : feature 1 commit db9cfb80676bb88506a7bfcbb08101ad7df594de (origin/dev1)Author : mmy <15224924822 @163 .com>Date : Thu May 16 14 :49 :13 2024 +0800 fix : description
需要将这3次提交squash成1次,并且修改提交信息
1 2 ➜ learn-git git:(dev1) git rebase -i HEAD~3
rebase信息修改前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pick 53adc27 feat: feature 1 pick 3874836 feat: lunch time pick 94a90c2 fix: brunch time# 变基 db9cfb8..94a90c2 到 db9cfb8(3 个提交) # # p, pick <提交> = 使用提交 # r, reword <提交> = 使用提交,但编辑提交说明 # e, edit <提交> = 使用提交,但停止以便修补提交 # s, squash <提交> = 使用提交,但挤压到前一个提交 # f, fixup [-C | -c] <提交> = 类似于 "squash" ,但只保留前一个提交 # 的提交说明,除非使用了 -C 参数,此情况下则只 # 保留本提交说明。使用 -c 和 -C 类似,但会打开 # 编辑器修改提交说明 # x, exec <命令> = 使用 shell 运行命令(此行剩余部分) # b, break = 在此处停止(使用 'git rebase --continue' 继续变基) # d, drop <提交> = 删除提交 # l, label <label> = 为当前 HEAD 打上标记 # t, reset <label> = 重置 HEAD 到该标记 # m, merge [-C <commit> | -c <commit>] <label> [ # . 创建一个合并提交,并使用原始的合并提交说明(如果没有指定 # . 原始提交,使用注释部分的 oneline 作为提交说明)。使用 # . -c <提交> 可以编辑提交说明。 # u, update-ref <引用> = 为引用 <ref> 设置一个占位符,以将该引用更新为此处的新提交。 # 此 <引用> 在变基结束后更新。 -- INSERT --
rebase信息修改后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pick 53adc27 feat: feature 1 s 3874836 feat: lunch time s 94a90c2 fix: brunch time# 变基 db9cfb8..94a90c2 到 db9cfb8(3 个提交) # # p, pick <提交> = 使用提交 # r, reword <提交> = 使用提交,但编辑提交说明 # e, edit <提交> = 使用提交,但停止以便修补提交 # s, squash <提交> = 使用提交,但挤压到前一个提交 # f, fixup [-C | -c] <提交> = 类似于 "squash" ,但只保留前一个提交 # 的提交说明,除非使用了 -C 参数,此情况下则只 # 保留本提交说明。使用 -c 和 -C 类似,但会打开 # 编辑器修改提交说明 # x, exec <命令> = 使用 shell 运行命令(此行剩余部分) # b, break = 在此处停止(使用 'git rebase --continue' 继续变基) # d, drop <提交> = 删除提交 # l, label <label> = 为当前 HEAD 打上标记 # t, reset <label> = 重置 HEAD 到该标记 # m, merge [-C <commit> | -c <commit>] <label> [ # . 创建一个合并提交,并使用原始的合并提交说明(如果没有指定 # . 原始提交,使用注释部分的 oneline 作为提交说明)。使用 # . -c <提交> 可以编辑提交说明。 # u, update-ref <引用> = 为引用 <ref> 设置一个占位符,以将该引用更新为此处的新提交。 # 此 <引用> 在变基结束后更新。 :wq
commit信息修改前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # 这是一个 3 个提交的组合。 # 这是第一个提交说明: feat: feature 1 # 这是提交说明 #2 : feat: lunch time # 这是提交说明 #3 : fix: brunch time # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Sat May 18 12 :36 :42 2024 +0800 # # 交互式变基操作正在进行中;至 db9cfb8 # 最后完成的命令(3 条命令被执行): # squash 3874836 feat: lunch time # squash 94 a90c2 fix: brunch time # 未剩下任何命令。 # 您在执行将分支 'dev1' 变基到 'db9cfb8' 的操作。 # # 要提交的变更:"~/develop/codes/learn-git/.git/COMMIT_EDITMSG" 28 L, 683 B
commit信息修改后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 feat: feature 1 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Sat May 18 12:36:42 2024 +0800 # # 交互式变基操作正在进行中;至 db9cfb8 # 最后完成的命令(3 条命令被执行): # squash 3874836 feat: lunch time # squash 94a90c2 fix: brunch time # 未剩下任何命令。 # 您在执行将分支 'dev1' 变基到 'db9cfb8' 的操作。 # # 要提交的变更: # 修改: README.md :wq
再次git log发现就只剩一条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 commit 6188 a860fc471e7f364a0d5348c78293df547a2a (HEAD - > dev1) Author: mmy < 15224924822 @163 .com> Date : Sat May 18 12 :36 :42 2024 + 0800 feat: feature 1 commit db9cfb80676bb88506a7bfcbb08101ad7df594de (origin/ dev1) Author: mmy < 15224924822 @163 .com> Date : Thu May 16 14 :49 :13 2024 + 0800 fix: descriptioncommit 38 f1ba6768ee74dcdc6dbaf04def41844474deda Author: mmy < 15224924822 @163 .com> Date : Thu May 16 14 :46 :29 2024 + 0800 first commit (END )
rebase to main 我们目前已经处理好本次提交的相关信息了,能不能直接推远端呢?
答案是不能
因为在我们开发的时候也有其他同学在开发新的功能,如果别人比我们开发得早,那我们这个feature肯定有冲突
无论如何都要解决冲突!
要想解决冲突,一定要在特性分支上rebase保证线性提交历史
本地main分支同步远程repo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ➜ learn-git git:(dev1) git checkout main 切换到分支 'main' 您的分支与上游分支 'origin/main' 一致。 ➜ learn-git git:(main) git pull origin main Enter passphrase for key '/Users/mmy/.ssh/id_rsa': remote: Enumerating objects: 1, done. remote: Counting objects: 100% (1/1), done. remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 展开对象中: 100% (1/1), 879 字节 | 879.00 KiB/s, 完成. 来自 github.com:hugtyftg/learn-git * branch main -> FETCH_HEAD 839752c..707c9cf main -> origin/main 更新 839752c..707c9cf Fast-forward 07 Rebasing into Head-3.svg | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 09 Rebase vs Merge.svg | 1 + README.md | 47 ++++++++++++++++++++++++++-- 3 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 07 Rebasing into Head-3.svg create mode 100644 09 Rebase vs Merge.svg
特性分支rebase main 1 2 3 4 5 6 7 8 9 10 11 12 ➜ learn-git git:(main) git checkout dev1 切换到分支 'dev1' 您的分支与上游分支 'origin/dev1' 一致。 ➜ learn-git git:(dev1) git rebase main 自动合并 README.md 冲突(内容):合并冲突于 README.md 错误:不能应用 6188a86.. . feat: feature 1 提示:Resolve all conflicts manually, mark them as resolved with 提示:"git add/rm <conflicted_files>" , then run "git rebase --continue" . 提示:You can instead skip this commit: run "git rebase --skip" . 提示:To abort and get back to the state before "git rebase" , run "git rebase --abort" . 不能应用 6188a86.. . feat: feature 1
有冲突的话需要解决冲突 1 2 3 4 5 6 7 8 9 10 11 12 13 feat: feature 1 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 交互式变基操作正在进行中;至 707c9cf # 最后完成的命令(1 条命令被执行): # pick 6188a86 feat: feature 1 # 未剩下任何命令。 # 您在执行将分支 'dev1' 变基到 '707c9cf' 的操作。 # # 要提交的变更: # 修改: README.md
冲突解决之后保存更改、继续rebase 1 2 3 4 5 ➜ learn-git git:(707 c 9 cf) ✗ git add . ➜ learn-git git:(707 c 9 cf) ✗ git rebase --continue [分离头指针 5 bca03 c ] feat: feature 1 1 file changed, 4 insertions(+), 1 deletion(-) 成功变基并更新 refs/heads/dev1 。
推送合入! 由于刚才已经给远程仓库push过一次了,所以这里需要强制推送覆盖远程dev1分支(万分注意-f )
1 ➜ learn-git git:(dev1) git push origin dev1 -f
推完之后可以发现pipeline又跑了一遍,并且这次没有conflicts了,可以准许合入。不过实际工作项目中还会有+1给你cr,ap之后才会合入……(ps: 实习阶段cr问题多千万要稳住心态,我曾经一个feat cr了6次才合入😭)