[前端漫談] 一巴掌拍平Git中的各類概念

0x000 導讀

git的文章不少,可是大部分都是一個套路,講概念,講命令,太多的概念和命令老是讓人有一種稀裏糊塗的感受,講的很對,但彷佛沒能講透,沒有醍醐灌頂的感受,大概是個人悟性差吧。因此這幾天一直在作各類git的實驗,而且閱讀了一些博客、文檔、資料,綜合下來整理出了這麼一篇文章。注意:html

  • 本篇文章旨在說明我對git的理解,只是一家之言,聊以分享。
  • 本片文章不是一篇命令教程,或者概念說明,須要必定的git使用經驗和踩坑經驗。
  • 爲了閱讀方便,commitID只保留4位

0x001 總結[提早]

這是一篇比較亂七八糟的文章,不從傳統出發,嘗試用本身的思想去理解git這一神奇的工具。之前我以爲git命運石之門,咱們在不一樣的時間線(分支)上跳躍,全部的事件都必須且只能發生在時間線上。可是如今我以爲git無限的可能性的集合,一個事件能夠引伸出無限的可能性。而咱們要作的是用工具(branch、tag、reset、rebase、merge....)來組織這些可能性,從而構成一個有序的、向前發展的歷史,引導整個歷史的發展,構建能夠走向將來的工程。git

0x002 存檔和讀檔

  • 存檔github

    其實吧,版本就是存檔,就是遊戲中的存檔,咱們不斷的推動項目,完成一個又一個任務,而後中途不斷的存檔,就造成了版本迭代。而版本多了,天然就須要管理了,天然就有了版本管理系統。shell

    在遊戲中,存檔能夠手動存檔,也能夠到指定點存檔,也能夠自動定場景存檔。在遊戲中,存檔以後造成的東西叫作檔案,而在git中,叫作commit。咱們可使用git add+git commit完成一個檔案的建立,或者說版本的建立。vim

    一個commit擁有許多的屬性,好比IDMessageDateAuthor:等等,這些信息都有助於咱們瞭解這個版本,就像遊戲中的存檔會以關卡名/圖片之類的信息來提示你這個存檔所表明的進度,好比使用git log能夠獲取如下信息:bash

    commit 4963 (HEAD -> master)
    Author: **********
    Date:   Thu Jan 10 15:22:12 2019 +0800
    
        版本H
    
    commit 1a42
    Author: **********
    Date:   Thu Jan 10 15:25:01 2019 +0800
    
        版本G
    
    commit 931b
    Author: **********
    Date:   Thu Jan 10 15:24:50 2019 +0800
    
        版本F
    ....
    複製代碼
  • 讀檔工具

    既然有存檔,那就有讀檔。遊戲中直接選擇一個檔案就好了,那git中呢?若是有可視化操做工具,那咱們直接點擊也是能夠的,但如今不使用工具,而使用命令行,該如何呢。讀取一個存檔說白了在git中就是讀取一個commit而已,因此咱們可使用git checkoutgit reset兩個命令來作到,那如何指定版本呢?前面提到的commit屬性中的ID能夠幫咱們實現這個目標。ui

    • 環境說明:我在倉庫中git commit了8個,每一個commit都添加了一個從a-h的文件,並在commit信息中添加版本標記
      2019-01-10-18-04-08
    • 使用git checkout切到版本A,能夠發現,此時只有文件a
      $ git checkout 401e
      Note: checking out '401e'.
      
      ...
      
      HEAD is now at 401e1b6 版本A
      
      $ ls
      README.md       a.txt
      複製代碼
    • 使用git reset切換到版本G,能夠發現,此時有了a-g幾個文件了
      $ git reset 1a42
      Unstaged changes after reset:
      D       b.txt
      D       c.txt
      D       d.txt
      D       e.txt
      D       f.txt
      D       g.txt
      
      $ git stash
      Saved working directory and index state WIP on (no branch): 1a4268d 版本G
      
      l$ ls
      README.md       a.txt           b.txt           c.txt           d.txt           e.txt           f.txt           g.txt
      複製代碼
  • 總結: 咱們經過commitID屬性配合其餘命令來達到了任意讀檔的目的,能夠在各類版本中隨意穿梭,快樂的很啊。而讀檔的姿式其實還有不少,但不外乎是對commit操做方式的不一樣,在git中,我以爲commit 纔是構成整個版本管理的基本栗子。每個commit都是獨立的個體,雖然和其餘commit存在着關聯,可是依舊是獨立的,而咱們在commit構成節點序列中來回移動和操做,就能夠達到全部對版本管理的目的。this

0x003 別名系統

在上一個章節中,咱們已經能夠依靠一些命令和commit ID作到在版本中自由的穿梭,可是卻帶來一個問題,那就是commit ID的記憶難度。commit IDhash值,儘管git支持只提供前幾位就能匹配到hash,而且也提供了commit message來講明commit,可是依舊存在commit的辨識和記憶問題。而這個問題,能夠經過別名系統來解決。spa

所謂的別名系統,實際上是我本身概括的概念,指的其實就是HEADbranchtag這三個東西。在我看來,這三個東西都是同樣的東西,都是別名,也就是標記一個commit的東西而已,只是在行爲表現上有一些區別。

  1. HEAD

    一個倉庫只有一個HEAD,指向你當前所在的commit。若是你建立了一個commitHEAD將會指向這個新的commit。也能夠經過命令,強制HEAD指向某個commit,好比resetcheckout。也就是不論你在哪一個commit之上,那麼HEAD就在哪兒,或者說,其實你能在哪一個commit,是經過修改HEAD指向的commit實現的。

    • 經過修改HEAD在各個版本之間旋轉跳躍

      2019-01-11-13-20-54

  2. branch

    一開始我以爲這個東西纔是git的核心,由於建立項目的時候,咱們就處於master分支之上,而且咱們在工做中,每每也是基於分支工做的。可是後來發現,分支在本質上毫無心義,並不須要真的基於branch去工做,基於commit就好了。而branch只是提供了一個方式來管理這些commit。branchHEAD相同點是隨着新的commit的建立,branch指向的commit會不斷更新,固然前提是你須要在這個branch所在的commit上建立新的commit。而branchHEAD的不一樣點在於HEAD只能有一個,branch能夠有多個。

    實驗一:用branch來實現切換版本

    • 目前的庫狀況
      $ git log --pretty=oneline
      1a42 (HEAD) 版本G
      931b 版本F
      071d 版本E
      0caa 版本D
      7855 版本C
      1295 版本B
      401e 版本A
      複製代碼
    • 爲版本A-G分別建立一個分支
      $ git checkout 1a42 -b G
      Switched to a new branch 'G'
      $ git checkout 931b -b F
      Switched to a new branch 'F'
      $ git checkout 071d -b E
      Switched to a new branch 'E'
      $ git checkout 0caa -b D
      Switched to a new branch 'D'
      $ git checkout 7855 -b C
      Switched to a new branch 'C'
      $ git checkout 1295 -b B
      Switched to a new branch 'B'
      $ git checkout 401e -b A
      Switched to a new branch 'A'
      
      $ git log --pretty=oneline
      1a42 (HEAD -> G) 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼
    • 接下來就能夠換一種方式在版本之間跳躍了,而且不須要記住或者查詢冗長的commit ID
      $ git checkout A
      Switched to branch 'A'
      $ git checkout B
      Switched to branch 'B'
      $ git checkout C
      Switched to branch 'C'
      $ git checkout E
      Switched to branch 'E'
      $ git checkout F
      Switched to branch 'F'
      $ git checkout G
      Switched to branch 'G'
      複製代碼

    實驗二:分支跟隨新的commit

    • 當前庫的狀況,注意:這裏的HEAD -> G表示HEAD指向了branch G,而branch G指向了版本G
      $ git log --pretty=oneline
      1a42 (HEAD -> G) 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼
    • 添加一個文件,建立一個commit
      $ echo 'h'> h.txt
      $ git add h.txt
      $ git commit -m '版本H'
      [G d346d27] 版本H
      1 file changed, 1 insertion(+)
      create mode 100644 h.txt
      複製代碼
    • 此時查看log,能夠看到HEADG都指向了版本H,就是所謂的branch跟着commit動,可是它真的是跟着commit動嗎?
      $ git log --pretty=oneline
      d346 (HEAD -> G) 版本H
      1a42 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼

    實驗三:分支跟着啥動

    • HEAD指向版本Gcommit,而不是分支G,也就是使用git checkout commitID,而不是使用git checkout branchName,能夠看到,此時HEAD不指向G,而是HEADG同時指向了版本Hcommit
      $ git checkout d346 # 版本 H 的 commitID
      $ git log --pretty=oneline
      d346 (HEAD, G) 版本H
      1a42 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼
    • 繼續建立一個commit,能夠看到,這個時候分支G再也不跟着commit移動了,因此,只有在HEAD指向branch的時候,branch纔會向前移動,也就是隻要HEAD來到branch身邊,branch就會跟着HEAD跑。
      $ echo 'i'> i.txt
      $ git add i.txt
      $ git commit -m "版本I"
      [detached HEAD 2e836eb] 版本I
      1 file changed, 1 insertion(+)
      create mode 100644 i.txt
      $ git log --pretty=oneline
      2e83 (HEAD) 版本I
      d346 (G) 版本H
      1a42 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼
  3. tag

    tag是比較特殊的一個別名類型,他沒法移動,或者說不推薦移動。一旦一個tag和指向某個coimmit,就不但願它移動,由於tag就是用來標記這個commit的,他是一個孤獨而忠誠的守望者,而不像branch,花間游龍似的浪子。

    • 如今庫的狀況
      $ git log --pretty=oneline
      1a42 (HEAD, G) 版本G
      931b (F) 版本F
      071d (E) 版本E
      0caa (D) 版本D
      7855 (C) 版本C
      1295 (B) 版本B
      401e (A) 版本A
      複製代碼
    • 爲每一個版本添加一個tag,爲了區別分支名,通通加了個T
      $ git tag TA A
      $ git tag TB B
      $ git tag TC C
      $ git tag TD D
      $ git tag TE E
      $ git tag TF F
      $ git tag TG G
      
      $ git log --pretty=oneline
      1a42 (HEAD, tag: G, G) 版本G
      931b (tag: TF, F) 版本F
      071d (tag: TE, E) 版本E
      0caa (tag: TD, D) 版本D
      7855 (tag: TC, C) 版本C
      1295 (tag: TB, B) 版本B
      401e (tag: TA, A) 版本A
      複製代碼
    • 如今又多了一種旋轉跳躍的方式了
      $ git checkout TA
      Previous HEAD position was 1a4268d 版本G
      HEAD is now at 401e1b6 版本A
      $ git checkout TB
      Previous HEAD position was 401e1b6 版本A
      HEAD is now at 1295260 版本B
      $ git checkout TC
      Previous HEAD position was 1295260 版本B
      HEAD is now at 7855905 版本C
      $ git checkout TD
      Previous HEAD position was 7855905 版本C
      HEAD is now at 0caa2b7 版本D
      $ git checkout TE
      Previous HEAD position was 0caa2b7 版本D
      HEAD is now at 071d00a 版本E
      $ git checkout TF
      Previous HEAD position was 071d00a 版本E
      HEAD is now at 931b3c9 版本F
      $ git checkout TG
      Previous HEAD position was 931b3c9 版本F
      HEAD is now at 1a4268d 版本G
      複製代碼
    • 總結 因此,不論是HEADtagbranch,都是一種別名,除了行爲表現上的差異,沒有太大的不一樣,特別是branchtag,不過都只是提供了一種管理commit的方式。

0x004 分叉

在上一章節中,咱們揭開了別名系統的紅蓋頭,這一章,咱們就開始探索一下分叉的神祕。

和遊戲中的存檔同樣,有時候一個遊戲有許多的選擇,這些選擇指向了不一樣的結果。而做爲遊戲玩家,咱們但願可以走完全部的選擇,以探索更多的遊戲樂趣。因此咱們會在作選擇的時候存檔,而當咱們走完一個選擇,就會讀取這個存檔,繼續往另外一個選擇探索。這個時候,就產生了兩個不一樣的劇情走向,這就是分叉。

git中,其實咱們能夠有無數的選擇,每個commit能夠建立無數的commit,就會引伸出無數的可能。

  • 咱們遇到了一個抉擇,因此須要建立版本,暫時稱爲版本X
    $ git log --pretty=oneline
    2cae (HEAD) 版本X
    ....
    複製代碼
  • 而後咱們選擇了走Y,而且沿着Y1一直走到Y3,這是盡頭
    $ git log --pretty=oneline
    d2e0 (HEAD) 版本Y3
    4ca8 版本Y2
    fcff 版本Y1
    2cae 版本X
    ...
    複製代碼
  • 接着咱們返回X,並選擇另外一個選擇Z,從Z1走到Z3
    $ git checkout 2cae # 切到`版本X`
    $ git log --pretty=oneline
    16ff (HEAD) 版本Z3
    0ca5 版本Z2
    b4a7 版本Z1
    2cae 版本X
    ...
    複製代碼
  • 總結

能夠看到,咱們順着兩個選擇一直往下發展,在這發展的過程當中,咱們徹底沒有用到tagbranch,也就是爲了印證commit 是構成 git 世界的基本栗子這一說明。

git log中,咱們看不到了Y走向,那Y真的消失了嗎?不是的,咱們依舊能夠經過Ycommit ID來尋回Y的記錄。固然爲了方便在YZ中切換,咱們可使用branch來標記一下YZ兩個走向,這樣就造成了YZ兩個branch了,也就是分叉!

那那些沒有被branch或者tag標記的commit呢?他們會消失嗎?會,也不會。不會是由於不被標記的commit將變成dangling commit,我稱之爲遊離的commit,是git中最孤獨的存在,只要咱們知道commitID,就會可喚回它。可是很大的多是咱們永遠不會記得這麼一個不被引用的commit,因此我呼籲,善待每個commit。會是由於仍是可能會被回收的,看這裏,git 也有 gc

0x003 合併

和遊戲的存檔不一樣的是,git中的版本能夠合併,也就是說我能夠在分支Y中作完任務Y1Y2Y3,而後分支Z中完成任務Z1Z2Z3,而後合併這兩個分支,結果回到了X,可是卻完成了Y1-y3Z1-Z3,並拿到了神器YZ,這讓boss怎麼活?

  • 實驗一:使用merge合併commit

    • 建立版本O
      $ echo O >> o.txt
      $ git add o.txt
      $ git commit -m '版本O'
      [detached HEAD 478fa6d] 版本O
      1 file changed, 1 insertion(+)
      create mode 100644 o.txt
      複製代碼
    • 基於版本O建立版本P1
      $ echo P >>p1.txt
      $ git add p1.txt
      $ git commit -m '版本P1'
      [detached HEAD a3ab178] 版本P1
      1 file changed, 1 insertion(+)
      create mode 100644 p1.txt
      $ git log --pretty=oneline
      a3ab (HEAD) 版本P1
      478f 版本O
      複製代碼
    • 基於版本O建立版本P2
      $ git checkout 478f # 版本O 的 commitID
      $ echo p2 >> p2.txt
      $ git add p2.txt
      $ git commit -m '版本P2'
      [detached HEAD cbccf52] 版本P2
      1 file changed, 1 insertion(+)
      create mode 100644 p2.txt
      $ git log --pretty=oneline
      cbcc (HEAD) 版本P2
      478f 版本O
      複製代碼
    • 合併版本P1版本P2
      $ git merge a3ab # 版本P1 的 commitID
      $ git log --pretty=oneline
      656a (HEAD) Merge commit 'a3ab' into HEAD
      cbcc 版本P2
      a3ab 版本P1
      478f 版本O
      複製代碼
  • 實驗三:使用rebase合併

    切換到版本P2,在版本P2中使用rebase

    $ git checkout cbcc # 版本P2 的 commitID
    ....
    HEAD is now at cbccf52 版本P2
    $ git rebase a3ab # 版本P1 的 commitID
    First, rewinding head to replay your work on top of it...
    Applying: 版本P2
    $ git log --pretty=oneline
    3bd7 (HEAD) 版本P2
    a3ab 版本P1
    478f 版本O
    複製代碼
  • 實驗四:使用cherry-pick合併

    • 切換到版本O,新建版本P3
      $ echo 'p3'>> p3.txt
      $ git add p3.txt
      $ git commig -m '版本P3'
      git: 'commig' is not a git command. See 'git --help'.
      
      The most similar command is
              commit
      $ git commit -m '版本P3'
      [detached HEAD ae09e94] 版本P3
      1 file changed, 1 insertion(+)
      create mode 100644 p3.txt
      $ git log --pretty=oneline
      ae09 (HEAD) 版本P3
      478f 版本O
      複製代碼
    • 切換到版本P2中使用cherry-pick合併版本P3的東西
      $ git checkout 3bd7 # 版本P2 的commitID
      ...
      HEAD is now at 3bd7820 版本P2
      $ git cherry-pick ae09 # 版本P3 的 commitID
      [detached HEAD f9dfba2] 版本P3
      Date: Sat Jan 12 11:35:27 2019 +0800
      1 file changed, 1 insertion(+)
      create mode 100644 p3.txt
      $ git log --pretty=oneline
      f9df (HEAD) 版本P3
      3bd7 版本P2
      a3ab 版本P1
      478f 版本O
      複製代碼
  • 注意:合併中的衝突解決

    合併的過程當中可能會出現衝突,好比同時拿到神器P1P2,可是在P1中賣掉了O以前拿到的裝備S,而在P2中則爲S鑲上了寶石,那麼合併以後要怎麼處理?是賣掉S?仍是保留鑲寶石的S?仍是鑲了寶石再賣掉?深井冰啊!我不要面子的啊... 因此這裏就涉及到了合併的衝突解決,這裏再也不贅述,不是我要講的內容。

0x005 變基

這個名詞讓人想入菲菲啊,每次項目新成員加入,老是會提醒他們注意要變基....

這裏不去說mergerebase的愛恨情仇,只說一些rebase的操做,用rebase來整理commit

上面說到commit 是構成 git 世界的基本栗子,因此,咱們須要掌握一些栗子的操做方式

  • 查看commit,可使用git log,若是須要尋回忘記的commit,可使用reflog來嘗試看看是否可以找到

    $ git log --pretty=oneline
    68de (HEAD -> X) Merge branches 'Y' and 'Z' into X
    16ff (Z) 版本Z3
    ...
    $ git reflog
    23e799e (HEAD) HEAD@{0}: rebase -i (pick): 版本Z
    01a10d6 HEAD@{1}: rebase -i (squash): 版本Y
    a15dd72 HEAD@{2}: rebase -i (squash): # This is a combination of 2 commits.
    b6f2ea3 HEAD@{3}: rebase -i (start): checkout 1004
    f4c4ccc HEAD@{4}: rebase -i (abort): updating HEAD
    ...
    複製代碼
  • 建立

    建立使用git add+git commit就好了

    $ echo error > error.txt
    $ git add error.txt
    $ git commit -m '一個錯誤的版本'
    [X bc90774] 一個錯誤的版本
    1 file changed, 1 insertion(+)
    create mode 100644 error.txt
    $ git log --pretty=oneline
    bc90 (HEAD -> X) 一個錯誤的版本
    68de Merge branches 'Y' and 'Z' into X
    ...
    複製代碼
  • 更新上一個commit,直接使用git commit --amend

    $ echo error2 >> error.txt
    $ git add error.txt
    $ git commit --amend
    // 這裏將打開一個vim窗口
    一個錯誤的版本
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    #
    # Date: Fri Jan 11 17:21:18 2019 +0800
    #
    # On branch X
    # Changes to be committed:
    # new file: error.txt
    #
    // 保存退出以後輸出
    [X d5c4487] 一個錯誤的版本
    Date: Fri Jan 11 17:21:18 2019 +0800
    1 file changed, 2 insertions(+)
    create mode 100644 error.txt
    複製代碼
  • 要更新歷史中的commit也是能夠作到的,例如須要在版本X中加入文件x1.txt,要使用交互式模式

    git rebase -i 2e83 # 指向 版本X 的前一個 commit
    複製代碼

    此時將打開一個交互式窗口

    pick 913b571 版本X
    pick 0eca5e3 版本Y1
    pick 33a9ca3 版本Y2
    pick b95b3ca 版本Y3
    pick 839c481 版本Z1
    pick 6fb6cb3 版本Z2
    pick c28d3e0 版本Z3
    ...
    複製代碼

    版本X前面的pick改成e或者edit,保存,而後退出,這個時候,倉庫將會回到版本X的狀態,並輸出

    Stopped at 913b571...  版本X
    You can amend the commit now, with
    
    git commit --amend
    
    Once you are satisfied with your changes, run
    
    git rebase --continue
    複製代碼

    添加文件x1

    $ echo x1 > x1.txt
    $ git add x*
    $ git commit --amend
    // 打開交互式窗口能夠修改 commit message
    $ git rebase --comtinue
    Successfully rebased and updated detached HEAD.
    複製代碼

    此時又回會到本來的版本而且多出了文件x1,就像是在版本X中就已經加入同樣

  • 插入一個新的commit,上面的栗子中不使用--amend,就會在XY1之間插入一個新的commit

    $ git rebase -i 2e83
    // 交互式窗口,吧`pick`改成`e`
    $ echo x2 > x2.txt
    $ git add x2.txt
    $ git commit -m '插入一個版本X2'
    [detached HEAD 1b4821f] 插入一個版本X2
    1 file changed, 1 insertion(+)
    create mode 100644 x2.txt
    $ git rebase --continue
    Successfully rebased and updated detached HEAD.
    $ git log --pretty=oneline
    30a5 (HEAD) 版本Z3
    4b00 版本Z2
    cc1d 版本Z1
    595e 版本Y3
    4456 版本Y2
    b6f2 版本Y1
    1b48 插入一個版本X2
    1004 版本X
    複製代碼
  • 刪除

    刪除一個分支可使用交互式rebase,命令:git rebase -i commitID,這裏的commitID必須是你要刪除的commit的前一個commit

    $ git rebase -i 68de
    複製代碼

    此時將會打開一個vim窗口

    pick bf2c542 版本Y1
    pick 588feec 版本Y2
    pick 1b2ae37 版本Y3
    pick 38f7cf3 版本Z1
    pick 080e442 版本Z2
    pick 206a7ae 版本Z3
    pick 6b01f70 一個錯誤的版本
    
    # Rebase 2caeda3..6b01f70 onto 2caeda3 (7 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    ...
    複製代碼

    要刪除一個錯誤的版本,將前面的pick改成d或者drop

    d 6b01f70 一個錯誤的版本
    複製代碼

    保存退出,輸出

    Successfully rebased and updated refs/heads/X.
    複製代碼
  • 合併多個commit,好比合並Z1-Z3,打開交互式窗口以後,將Z2Z3pick改成s

    $ git rebase -i 100468330c7819173760938d9e6d4b02f37ba001
    // 打開了交互式窗口
    pick bf2c542 版本Y1
    pick 588feec 版本Y2
    pick 1b2ae37 版本Y3
    pick 38f7cf3 版本Z1
    s 080e442 版本Z2
    s 206a7ae 版本Z3
    複製代碼

    保存退出之後,又打開交互式窗口,顯示要合併的commitmessage,這裏能夠修改commit

    # This is a combination of 3 commits.
    # This is the 1st commit message:
    
    版本Z1
    
    # This is the commit message #2:
    
    版本Z2
    
    # This is the commit message #3:
    
    版本Z3
    複製代碼

    這裏修改成Z,保存,退出,輸出,能夠看到,Z1-Z3消失了,取而代之的是Z,對Y1-Y3作操做

    detached HEAD f4c4ccc] 版本Z
    Date: Fri Jan 11 16:27:00 2019 +0800
    1 file changed, 3 insertions(+)
    create mode 100644 z.txt
    Successfully rebased and updated detached HEAD.
    $ git log --pretty=oneline
    f4c4 (HEAD) 版本Z
    595e 版本Y3
    4456 版本Y2
    b6f2 版本Y1
    
    $ git rebase -i 1004
    [detached HEAD 01a10d6] 版本Y
    Date: Fri Jan 11 16:24:37 2019 +0800
    1 file changed, 3 insertions(+)
    create mode 100644 y.txt
    Successfully rebased and updated detached HEAD.
    $ git rebase --continue
    複製代碼
  • 從新排序commit順序,好比重排版本Y版本Z,交換一下順序就行了

    $ git log --pretty=oneline
    23e7 (HEAD) 版本Z
    01a1 版本Y
    $ git rebase -i 1b48
    複製代碼

    這時候打開交互式窗口,顯示

    pick a1942a3 版本Y
    pick eeabc6c 版本Z
    複製代碼

    將它交換順序,保存,退出

    pick eeabc6c 版本Z
    pick a1942a3 版本Y
    複製代碼

    查看結果

    Successfully rebased and updated detached HEAD.
    $ git log --pretty=oneline
    a194 (HEAD) 版本Y
    eeab 版本Z
    複製代碼

0x006 資料

相關文章
相關標籤/搜索