姐姐問我什麼是變基操作(git-rebase)

2021-02-21 Golang夢工廠
前言

哈嘍,everybody,不知不覺8天的小長假也接近了尾聲,玩耍了這麼多天,今天也要收一收心,開始學習了呦~。明天就要上班啦,今天姐姐突然問我git-rebase指令是幹什麼的,怎麼用?其實我是不想給他講的,但是還是沒有逃過姐姐的軟磨硬泡,那麼我們就一起來看一看什麼是git-rebase吧!!!

緣起

話說,我和姐姐的緣分是在那一個月黑風高的晚上,啪,姐姐一巴掌打在了我的臉上並說了一句:能不能講重點~~~。哈哈,不開玩笑了,直接說重點吧。我們先來看一個場景,我查看了一下我github上的個人倉庫,commit提交次數很多,提交內容如下:

這麼多的提交,有很多沒有規範的命名,因為是自己使用,就隨便開整了,這確實不好,還有一些沒有必要的提交,其實是可以合併到一起的,這樣會導致如下問題:

造成分支汙染,項目中充滿了許多commit記錄,當出現緊急問題需要回滾代碼時,就只能一條條的查看了。代碼review不方便,當你要做code review時,一個很小的功能卻提交了很多次,看起來就不是很方便了。

這一篇文章我們先不講git提交規範,我們先來解決一下如何合併多次提交記錄。

rebase作用一:合併提交記錄

通過上面的場景,我們可以引申出git-rebase的第一個作用:合併提交記錄。現在我們想合併最近5次的提交記錄,執行:

$ git rebase -i HEAD~2

執行該指令後會自動彈出vim編輯模式:

pick e2c71c6 update readme
pick 3d2c660 wip: merge`

# Rebase 5f47a82..3d2c660 onto 5f47a82 (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

從這裡我們可以看出前面5行是我們要合併的記錄,不過前面都帶了一個相同的指令:pick,這是什麼指令呢,不要慌,這不,下面已經給出了commands:

pick:保留該commit(縮寫:p)

reword:保留該commit,但我需要修改該commit的注釋(縮寫:r)

edit:保留該commit, 但我要停下來修改該提交(不僅僅修改注釋)(縮寫:e)

squash:將該commit和前一個commit合併(縮寫:s)

fixup:將該commit和前一個commit合併,但我不要保留該提交的注釋信息(縮寫:f)

exec:執行shell命令(縮寫:x)

drop:我要丟棄該commit(縮寫:d)

label:用名稱標記當前HEAD(縮寫:l)

reset:將HEAD重置為標籤(縮寫:t)

merge:創建一個合併分支並使用原版分支的commit的注釋(縮寫:m)

根據這些指令,我們可以進行修改,如下:

pick e2c71c6 update readme
s 3d2c660 wip: merge`

修改好後,我們點擊保存退出,就會進入注釋界面:

# This is a combination of 2 commits.
# This is the 1st commit message:

update readme

# This is the commit message #2:

wip: merge`

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Sep 17 22:03:52 2020 +0800
#
# interactive rebase in progress; onto 5f47a82
# Last commands done (2 commands done):
#    pick e2c71c6 update readme
#    squash 3d2c660 wip: merge`
# No commands remaining.
# You are currently rebasing branch 'master' on '5f47a82'.
#
# Changes to be committed:
#       new file:   hash/.idea/.gitignore
#       new file:   hash/.idea/hash.iml
#       new file:   hash/.idea/misc.xml
#       new file:   hash/.idea/modules.xml
#       new file:   hash/.idea/vcs.xml
#       new file:   hash/go.mod
#       new file:   hash/hash/main.go
#       modified:   snowFlake/Readme.md

上面把每一次的提交的meassage都列出了,因為我們要合併這兩次的commit,所以提交注釋可以修改成一條,最終編輯如下:

# This is a combination of 2 commits.
# This is the 1st commit message:

fix: merge update and wip: merge`

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Sep 17 22:03:52 2020 +0800
#
# interactive rebase in progress; onto 5f47a82
# Last commands done (2 commands done):
#    pick e2c71c6 update readme
#    squash 3d2c660 wip: merge`
# No commands remaining.
# You are currently rebasing branch 'master' on '5f47a82'.
#
# Changes to be committed:
#       new file:   hash/.idea/.gitignore
#       new file:   hash/.idea/hash.iml
#       new file:   hash/.idea/misc.xml
#       new file:   hash/.idea/modules.xml
#       new file:   hash/.idea/vcs.xml
#       new file:   hash/go.mod
#       new file:   hash/hash/main.go
#       modified:   snowFlake/Readme.md

編輯好後,保存退出就可以了。這樣就完成了一次合併commit。我們來驗證一下:

$ git log
15ace34 (HEAD -> master) fix: merge update and wip: merge`
5f47a82 update snowFlake code

從這裡我們可以看到,兩次提交變成了一次,減少了無用的提交信息。

作用二:分支合併

這個作用我們使用的很少,但是還是要知道,下面我們一起來看一下使用場景。

假設我們現在有一個新項目,現在我們要從master分支切出來一個dev分支,進行開發:

$ git checkout -b dev

這時候,你的同事完成了一次 hotfix,並合併入了 master 分支,此時 master 已經領先於你的 dev 分支了:

同事修復完事後,在群裡通知了一聲,正好是你需要的部分,所以我們現在要同步master分支的改動,使用merge進行合併:

$ git merge master

圖中綠色的點就是我們合併之後的結果,執行git log就會在記錄裡發現一些 merge 的信息,但是我們覺得這樣汙染了 commit 記錄,想要保持一份乾淨的 commit,怎麼辦呢?這時候,git rebase 就派上用場了。

所以現在我們來試一試使用git rebase,我們先回退到同事 hotfix 後合併 master 的步驟,我現在不使用merge進行合併了,直接使用rebase指令

$ git rebase master

這時,git會把dev分支裡面的每個commit取消掉,然後把上面的操作臨時保存成 patch 文件,存在 .git/rebase 目錄下;然後,把 dev 分支更新到最新的 master 分支;最後,把上面保存的 patch 文件應用到 dev 分支上;

從 commit 記錄我們可以看出來,dev 分支是基於 hotfix 合併後的 master ,自然而然的成為了最領先的分支,而且沒有 merge 的 commit 記錄,是不是感覺很舒服了。

我們在使用rebase合併分支時,也會出現conflict,在這種情況下,git 會停止 rebase 並會讓你去解決衝突。在解決完衝突後,用 git add 命令去更新這些內容。然後再次執行git rebase --continue,這樣git 會繼續應用餘下的 patch 補丁文件。

假如我們現在不想在執行這次rebase操作了,都可以通過--abort回到開始前狀態:

git rebase --abort

rebase是存在危險的操作 - 慎用

我們現在使用rebase操作看起來是完美的,但是他也是存在一定危險的,下面我們就一起來看一看。

現在假設我們在dev分支進行開發,執行了rebase操作後,在提交代碼到遠程之前,是這樣的:

提交dev分支到遠程代碼倉庫後,就變成了這樣:

而此時你的同事也在 dev 上開發,他的分支依然還是以前的dev,並沒有進行同步master:

那麼當他 pull 遠程 master 的時候,就會有丟失提交記錄。這就是為什麼我們經常聽到有人說 git rebase 是一個危險命令,因為它改變了歷史,我們應該謹慎使用。

不過,如果你的分支上需要 rebase 的所有 commits 歷史還沒有被 push 過,就可以安全地使用 git-rebase來操作。

總結

在asong的細心講解下,姐姐完全搞懂了怎麼使用git rebase,我們來看一下姐姐的總結:

當我們在一個過時的分支上面開發的時候,執行 rebase 以此同步 master 分支最新變動;假如我們要啟動一個放置了很久的並行工作,現在有時間來繼續這件事情,很顯然這個分支已經落後了。這時候需要在最新的基準上面開始工作,所以 rebase 是最合適的選擇。git-rebase 很完美,解決了我們的兩個問題:使用rebase操作要注意一個問題,如果你的分支上需要 rebase 的所有 commits 歷史還沒有被 push 過,就可以安全地使用 git-rebase來操作。

看來姐姐是真的學會了,那你們呢?

沒有學會不要緊,親自試驗一下才能更好的理解呦~~~。

好啦這一篇文章到這裡就結束了,我們下期見。

參考文章連結:http://jartto.wang/2018/12/11/git-rebase/

結尾給大家發一個小福利吧,最近我在看[微服務架構設計模式]這一本書,講的很好,自己也收集了一本PDF,有需要的小夥可以到自行下載。獲取方式:關注公眾號:[Golang夢工廠],後臺回覆:[微服務],即可獲取。

我翻譯了一份GIN中文文檔,會定期進行維護,有需要的小夥伴後臺回復[gin]即可下載。

我是asong,一名普普通通的程序猿,讓我一起慢慢變強吧。我自己建了一個golang交流群,有需要的小夥伴加我vx,我拉你入群。歡迎各位的關注,我們下期見~~~

推薦往期文章:

相關焦點

  • 對比 git pull和 git pull --rebase的使用區別
    首選區別這兩個操作:git pull = git fetch + git merge
  • Git 自救指南:這些坑你都跳得出嗎?
    但是一分耕耘一分收穫,如果想更好地掌握 git,需要付出大量的學習成本。即使在各種 GUI 的加持下,也不得不說 git 真的很難,在 V2EX 上也常有如何正確使用 git 的討論,同時在 Stackoverflow 上超過 10w+ 的 git 相關問題也證明了 git 的複雜性。
  • 我問老媽吃過什麼虧,老媽說,生了你們仨
    老媽總說我從小雞賊。我問老媽:「我不吃糊塗虧而已。您說,我欠過誰嗎?」她沉思很久,說:「沒,除了你媽。」
  • 《情熱傳說》手記:基不基情你們說了算
    《情熱傳說》,其實早在這款遊戲出主機版的時候蘑菇就聽到自己的基友說一定不要錯過了,我問為啥,她答:「因為實在是太基了,不玩不行啊。」我:「……」好吧,我要承認和資深老腐女比起來我就是一杯白開水,哎,你們別不信啊,在這個宅基腐橫行的時代裡,我作為一個為數不多的正經人是多麼不容易啊。於是,頂著我家小水管我又開始了瘋狂下載,從早上出門上班開始到夜幕下班回家,這款11G大小的遊戲終於被我下好了。用啥玩好?按照移植遊戲的一貫尿性,有手柄一定不要用鍵盤。
  • 微生物小知識:微生物培養基都有什麼類型?
    1、按照培養基的成分來分 培養基按其所含成分,可分為合成培養基、天然培養基和半合成培養基三類。(1)合成培養基。合成培養基的各種成分完全是已知的各種化學物質。這種培養基的化學成分清楚,組成成分精確,重複性強,但價格較貴,而且微生物在這類培養基中生長較慢。如高氏一號合成培養基、察氏(Czapek)培養基等。
  • 《偽裝夫婦》:一對百合一對基!
  • 想看我和七哥,線下面基!
    「我想看你倆的合照,單獨發給我一張吧」「我很期待你倆的合照,看看是什麼大帥哥」「關注你倆好久了,能看看照片嗎?」.每天后臺都會收到關於看我倆合照的私信,在這裡我想統一告訴大家:我和七哥真的不方便,抱歉,我們不露臉。
  • 我姐姐讓我加你,有事請教一下
    「我姐姐叫我加你對方不僅能準確無誤地叫出自己的名字且都聲稱是「我姐姐讓我加你」但你此時若掉以輕心按下同意按鈕一個新的詐騙套路就在前方等待著你……近日,網友小朱反映,27日下午,她收到一條微信好友申請,對方稱:「XX(小朱名字),你好,我姐姐要我加你有事請教,請通過下!」
  • 如果你問我Les是什麼…?
    隨時隨地了解圈類各種新鮮事兒……如果你問我les是什麼?…首先讓我們用一個可能算不上笑話的笑話開頭▼ 【我有一個拉拉朋友,長的很美,每次朋友圈po我們的合照都有直男朋友跑來問我「有美女也不介紹給我」!我說「是拉拉」。對方一般都會回「什麼拉拉,被男人xxx過就會知道男人的好了。」
  • 我媽問我:你天天在家看日劇,又不會說日語有什麼用?
    前一陣和老媽一起去日本旅遊結果她問我:「我看你天天在家看日劇,怎麼一句都不會說啊,我帶你出來有什麼用啊!
  • GitBubble 原型設計師來跟你聊聊這個小遊戲的那些事!
    >今天,我們邀請到了這款遊戲最初的原型設計者 George 來跟我們一起聊聊關於 GitBubble 的那些事兒~寫在GitBubble上線之後「在一個晚上,我的母親問我,今天怎....麼不開心?」這裡有個小插曲:為了給我的 PM 演示我到底要什麼效果,我不得不在 Presentation 裡一個個加好動畫效果,使它看起來像那麼回事兒,下面是當年的效果(說多了都是淚)。
  • 雷雨夜我的秘密被發現,姐姐強迫給我穿文胸
    閃電一過,我連忙打開廁所的燈,把姐姐的文胸雙手託住,湊到鼻子前,正準備好好聞聞姐姐的體香時。我突然萌生了一個大膽的想法——既然姐姐可以戴,那為什麼我不可以呢,說不定我戴上後也可以像姐姐一樣。  我連睡衣都沒脫,直接開始戴文胸,手先穿過去,調整好肩帶,把罩杯擺正,但是接下來最大的問題是背扣我扣不上呀。
  • 代嫁新娘:男主逼婚,姐姐逃嫁,妹妹代嫁
    (不你想多了,你真的想多了,竟然13集還沒甜甜的寵溺片段)劇情簡介:      因為同父異母的弟弟欠下了賭債被人逼債,男主「英雄救男」,但是作為交換的條件就是——要娶姐姐(fon)。      什麼,姐姐要嫁給一個素未謀面的陌生人?暴躁小妹(roong)向我們真正展示了什麼叫做「救姐jia反而把自己搭進去」——讓姐姐逃婚,沒有新娘看你怎麼結婚。
  • 6歲姐姐打哭2歲弟弟的視頻火了 網友:我姐姐可能是假姐姐…
    「你剛才打我25下,我都沒哭,我就打你7下,你就哭啦?」「你要是親姐姐,姐姐也親你。」「你打別人,別人也會打你;你幫助別人,別人也會幫助你……你對別人怎麼樣,別人就會對你怎麼樣!」 村口賣菜的李大爺:沒毛病!這姐姐長大後可不一般!魏什麼乜:姐姐不是一般的懂事!
  • 我的姐姐的丈夫的爸爸的妹妹的女兒叫什麼,知道答案的快進來!
    在《我不是潘金蓮》中有一句經典的臺詞,後山嶺的陳阿大是你表舅吧,陳阿大他老婆的娘家是崔家塢的,我姨家有一個表妹嫁給了陳阿大他老婆的妹妹的一個叔伯侄子我爸爸的兒子的弟弟的女兒的姐姐的媽媽的哥哥的爸爸的兒子的媽媽的女兒的姐姐的哥哥的媽媽的丈夫的兒子的弟弟的妻子的兒子的妻子的丈夫的爸爸的爸爸的弟弟的兒子的爸爸的哥哥的兒子的是誰?(答案在後面)
  • 妹子問我:SM是什麼意思啊?
    NO.1前天,一妹子問我:SM是什麼意思啊?  我靈機一動,我告訴她說是失眠的意思!  昨天,發現妹子更新了朋友圏:最近經常SM,太痛苦了!什麼時候才能熬到天亮呀! 今天,我被拉黑了!兒子這幾天會叫爸爸媽媽了,我高興的叫來爸媽和嶽父嶽母來家裡吃飯。席間我抱著小傢伙:來寶貝叫聲爸爸。 兒子:爸爸。 「還會叫什麼?」 「媽媽」 我逗他:還會別的嗎? 兒子:老公! 眾人被他逗的笑成一團。 我又問:還有呢?
  • 日劇《偽裝夫婦》:掰直還是掰彎,百合還是基
    作為一部最近大火的熱播日劇,《偽裝夫婦》的看點除了女王天海佑希的顏值以及她內心os以外,那絕對是一對百合一對基!
  • 我要把你定下來!高調求婚「姐姐」曾經的劈腿愛好者林宥嘉忘了和鄧紫棋的十年了嗎?
    今日,林宥嘉在微博發布求婚成功大他三歲的「姐姐「」丁文琪,還十分肉麻的稱「我要把你定下來」 瞬間刷爆了朋友圈,在一片哀嚎中自然少不了提起林宥嘉和前女友鄧紫棋十年戀情以撕破臉告吹的那一場大戰。曾有記者在機場向返港的鄧紫棋提問,而她則憤怒直言「我不想提這個人」!鄧小姐到底為何如此震怒...在後來的採訪中,她給出了答案,出軌!愛玩消失!餐廳攬女!在基吧跟member們表現曖昧! 素有情歌王子美名的yoga讓人大跌眼鏡。
  • 洪真英姐姐面貌大變引韓網友群嘲:照片太嚇人…
    歌手洪真英的姐姐洪善英公開了自己容貌發生變化的樣子。25일 홍선영은 자신의 인스타그램 계정에 셀카를 게재했다. 홍선영은 사진과 함께 "이제 여름!!!다들 열심히 관리하고 계신가요? 저도 너무 큰부담없이 맛있게 열심히 하고있어요^^"라고 글을 남겼다.25日,洪善英在個人Instagram上上傳了自拍,並配文:「到夏天了!!!
  • 一女網友問我,SM是什麼意思?
    一女網友問我,SM是什麼意思?我以為她懂,故意來找點話題什麼的,我就說是失眠的意思…第二天早看見她發了一條這樣的說說:最近經常SM,有點受不了了,不過今天還好,再過兩個小時天就亮了,來吧,SM,熬過就好了!……中午被她臭罵一頓,拉黑我了,我心裡特憋屈…