大家好,我是 Kagol,Vue DevUI 開源元件庫和 EditorX 富文字編輯器建立者,專注於前端元件庫建設和開源社群運營。
前兩天檢視程式碼時,發現PR裡面有兩個提交的描述資訊一模一樣,於是我提出應該將這兩個提交合併成一個,保持提交樹的清晰。
先儲存起來!
而同事這時正在開發別的特性,工作區不是乾淨的,沒法直接執行 git rebase 操作,於是很自然地執行
git stash
將正在修改的內容儲存到一個棧中,並維持當前工作區乾淨。
這樣就可以執行切換分支、變基等操作,這些操作能執行的前提是當前工作區是乾淨的。
變基吧!少年!
我們先執行 git log 命令,找到要合併的兩個提交之前的那個提交:cdedd430
commit ec0218ff
feat: 增加國際化
commit 89f3d02c
feat: 增加國際化
commit cdedd430
refactor: pnpm工程改造
然後執行 git rebase 變基命令:
git rebase -i cdedd430
這時會進入一個互動式命令列介面:
pick 89f3d02 feat: 增加國際化
pick ec0218f feat: 增加國際化
# Rebase cdedd43..ec0218f onto cdedd43 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
"~/my-project/.git/rebase-merge/git-rebase-todo" 28L, 1232B
這時你可以移動游標,但是無法輸入字元,因為這是個只讀的介面,需要先輸入 i 字元進入編輯態,此時介面底部會出現 -- INSERT --
標識。
...
# Note that empty commits are commented out
-- INSERT --
下面那些以 # 開頭的都是註釋,只有前面兩行比較關鍵。
pick 89f3d02 feat: 增加國際化
pick ec0218f feat: 增加國際化
# ...
每一行都由三部分組成:
- Command:需要執行的命令
- Commit ID:提交 ID
- Commit message:提交的描述資訊
我們需要將 ec0218f 合併到 89f3d02 上,因此需要將第二行的 pick 改成 squash(s) 或 fixup(f),這兩個命令的區別在於:
- squash(s) 是將當前的提交合併到上一行的提交上,保留兩個提交的描述資訊,可以在下一步中進行提交資訊的編輯
- fixup(f) 也是將當前的提交合併到上一行的提交上,但不保留當前提交的描述資訊
由於我們兩次提交資訊完全一致,沒必要保留,選擇 fixup(f):
pick 89f3d02 feat: 增加國際化
f ec0218f feat: 增加國際化
修改好之後,先按 ESC 退出編輯態,然後按 :wq 儲存,顯示以下資訊說明變基成功,兩個提交已經合併在一起
Successfully rebased and updated refs/heads/kagol/test-rebase.
執行 git log 看下效果:
commit 86930d03
feat: 增加國際化
commit cdedd430
refactor: pnpm工程改造
可以看到兩個提交已經合併在一起,並且生成了一個新的 Commit ID: 86930d03。
我程式碼沒了!
1小時之後,同事慌慌張張地跟我說:
我程式碼沒了!
我心裡第一反應是:
剛才一頓變基猛如虎,不過變基變出問題來了吧?
作為一個成熟穩重的程式設計師,什麼大風大浪沒見過,於是輕輕地回了句:
少年,莫慌!你先講下你剛才做了什麼?
我沒,沒做什麼...
沒做什麼程式碼怎麼會自己丟了呢?
我就執行了一下 git stash pop,然後我之前寫了一上午的程式碼就沒...沒了...
突然開始心裡有點慌,把同事一上午程式碼搞沒了,我怎麼賠給人家??
但心裡不能表現出來,不著急,穩住少年!
你先執行下 git stash list 看下儲存棧裡還有沒有內容:
$ git stash list
stash@{0}: WIP on master: f90abfe Initial commit
看到之前儲存的內容還在我立馬不慌了!
不再執行下 git stash pop,我看下有沒有報什麼錯?
執行完之後果然報了一個錯:
$ git stash pop
error: Your local changes to the following files would be overwritten by merge:
main.ts
Please commit your changes or stash them before you merge.
Aborting
The stash entry is kept in case you need it again.
大意是:
你本地修改了檔案,儲存棧裡的內容如果彈出會覆蓋掉你本地的程式碼,所以導致操作失敗。
然後建議你先提交你本地的修改或者將你本地的修改儲存起來。
並且特意提示你你儲存的內容給你保留下來了,方便你下次要用的時候可以用。
不得不說,這 Git 真是太貼心了,考慮得很周到,為 Git 點個贊?
雖然我其實已經猜到是什麼原因了,但是作為成熟穩重的程式設計師,我依然不動聲色地問了句:git rebase 之後,git stash pop 之前,中間你是不是還改了什麼東西?
哦,好像是改了 main.ts 檔案,我想起來了!
你把你改的東西先撤銷下,然後執行 git stash pop 試試?
破案!收工!
果然,執行 git stash pop 成功,之前的上百行程式碼都找回來了!
破案!收拾吃飯的傢伙,準備收工!
哦,不行,還有兩個小時才下班...
我是 Kagol,如果你喜歡我的文章,可以給我點個贊,關注我的掘金賬號和公眾號 Kagol
,一起交流前端技術、一起做開源!