多人开发的正确工作流程 在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次才合入😭)