git簡明使用手冊

git作為時下最流行的代碼管理工具,Git權威指南總結了十條喜歡Git的理由

  • 異地協同工作;
  • 現場版本控制;
  • 重寫提交說明;
  • 無盡的后悔藥;
  • 更好用的提交列表;
  • 更好的差異比較;
  • 工作進度保存;
  • 作為SVN前端實現移動辦公;
  • 無處不在的分頁器;
  • 快。

其中:

1. 概述

1.1 git客戶端安裝

1.2 git客戶端配置

遠程倉庫可以通過網頁方式訪問,但通常情況下仍然需要創建本地倉庫:

  1. 創建本地 SSH key:

    • Windows下打開Git Bash,Linux下打開終端;
    • 執行ssh-keygen,所有提示均回車確認,生成私鑰和公鑰:

      <當前用戶根目錄>/.ssh/id_rsa
      <當前用戶根目錄>/.ssh/id_rsa.pub

    • 查看公鑰文件內容并復制,注意不要復制命令本身

      cat <當前用戶根目錄>/.ssh/id_rsa.pub

  2. 添加遠程倉庫訪問權限,不同的服務器會有不同的配置方法:

    • GitHub需要從右上角頭像右側的向下箭頭進入settings->SSH and GPG keys來添加或者直接通過GitHub客戶端自動添加;
    • gitolite需要將SSH公鑰拷貝到gitolite-admin目錄下的keydir目錄中,并需要gitolite.conf已配置合適的訪問權限。

    注意:

    • 本機SSH 私鑰id_rsa不能刪除。
    • 本機SSH key只需要創建一對,不需要為每個服務器都創建一對。
  3. 創建本地倉庫并配置

    • 回到Git Bash/終端;
    • 執行

      git clone ssh://xxx.git

    • 執行本地配置(更多配置參見自定義-Git-配置-Git

      git config --global user.name “姓名”
      git config --global user.email “郵箱”
      git config --global color.ui auto
      git config --global core.ignorecase false

      git config --global core.filemode false
      git config --global core.autocrlf input
      git config --global core.safecrlf true
      git config --global push.default simple
      git config --global rerere.enabled true
    • 配置完成后可顯示本地配置信息

      git config -l --global

    注意

    • 自動補齊: Windows客戶端默認支持命令補齊,服務器上Linux已經配置自動補齊,自行安裝的Linux需要參考Git基礎-技巧和竅門進行配置;
    • 命令別名:git允許為常用操作設置別名,以簡化操作(參見Git-基礎-Git-別名):

    git config --global alias.ci commit
    git config --global alias.unstage 'reset HEAD --'

2. git基礎

2.1 基本工作流程

2.2 獲取幫助信息

2.3 合并比較結果閱讀

git支持外部比較/合并工具(參見外部的合并與比較工具配置說明),但通常使用更為直接的命令行方式:

  • diff結果閱讀
--- a/src/test.txt  :原始文件(以---開頭) 
+++ b/src/test.txt  :目標文件(以+++開頭) 
@@ -1,3 +1,3 @@     :當前差異塊的比較對象為原始文件的第1行開始的3行與目標文件的地1行開始的3行
-orign              :只存在于原始文件(以-開頭) 
+modified           :只存在于目標文件(以+開頭)  
以空格開頭           : 同時存在于原始文件和目標文件
  • merge結果閱讀
<<<<<<<
當前分支代碼
=======_
其他分支合并進來的代碼
>>>>>>>

2.4 提交(commit)消息格式

git提交消息是日志回溯/代碼審查/二分法問題查找的基礎,建議參考thoughtbot規范

50-character subject line

1. Why was this change necessary?

2. How does it address the problem?

3. Are there any side effects?

建議將模板保存在根目錄下,使用如下命令配置為模板,這樣在提交時就會自動顯示:

git config --global commit.template <模板文件>

3. git倉庫構成及訪問路徑

Paste_Image.png

3.1 遠程倉庫

遠程倉庫是服務器上的git倉庫,支持如下常用操作(更多操作參見Git-基礎-遠程倉庫的使用):

3.1.1 基本操作

  • 查看本地倉庫遠程倉庫列表

    git remote -v

    如下所示:

    $ git remote -v
    origin  ssh://xxx.git (fetch)
    origin  ssh://xxx.git (push)
    

    注意:每個本地倉庫可以從多個遠程倉庫獲取代碼,當前僅包含一個遠程倉庫origin。

  • 查看遠程倉庫概況

    git remote show <遠程倉庫名稱>

    如下所示:

Paste_Image.png

該操作可用于查看遠程倉庫的地址,分支情況,與本地分支的差別等等。

3.1.2 從遠程倉庫到本地倉庫

  • 創建新的本地倉庫

    git clone <遠程倉庫路徑> <可選的本地倉庫目錄名稱>

  • 從遠程倉庫獲取最新內容,包括新的分支以及原有分支上的改動

    git fetch

  • 從遠程倉庫獲取最新內容,并合并到當前分支

    git pull

    注意:

    • 該操作相當于git fetch + git merge origin/<當前分支名稱>,因此出現沖突時可以使用git merge --abort來終止;
    • 如果發生沖突,應當順序執行如下操作:
      • 使用git merge --abort終止本次操作;
      • 使用git checkout -b temp創建并切換到1個臨時分支;
      • 使用git branch -D <當前分支名稱>刪除當前分支;
      • 使用git checkout <當前分支名稱>重新從遠程分支創建本地分支;
      • 使用git branch -D temp刪除臨時分支。
    • !!!請勿使用--rebase選項,除非你知道你在干什么!!!

3.1.3 從本地倉庫到遠程倉庫

  • 本地倉庫更新到遠程倉庫

    git push

    注意

    • 若本地分支在遠程倉庫中沒有對應的分支,則本操作會在遠程倉庫中創建同名分支并自動關聯;
    • 若與遠程倉庫代碼沖突且確認本地倉庫沒有問題,例如使用git rebase與master分支同步后,則可以使用git push --force來強制推送到服務器,從而使用本地倉庫覆蓋遠程倉庫;此時,遠程倉庫中的修改日志將會丟失

3.2 本地倉庫

本地倉庫是當前工作機器上的git倉庫,支持如下常用操作:

3.2.1 查看本地倉庫狀態

  • 查看總體狀態

    git status

Paste_Image.png

命令結果中注釋如下:

  • 注1: 本地倉庫當前分支名稱;
  • 注2: 本地倉庫當前分支與遠程倉庫同名分支之間的差異;
  • 注3: 推薦執行的操作;
  • 注4: 暫存區(stage)內容;
  • 注5: 工作區內容,對倉庫中文件的修改;
  • 注6: 工作區內容,未加入到倉庫中的文件。

3.2.2 查看本地倉庫日志(參見Git-工具-選擇修訂版本

  • 查看所有或某個文件的修改記錄

    git log <可選文件路徑>

  • 查看所有或某個文件的修改記錄的概要(修改文件列別行數等)

    git log --stat <可選文件路徑>

  • 圖形化簡略模式查看倉庫日志

    git log --oneline --graph

    注意:在提交pull request之前,建議使用該命令確認需要合入主線的分支上沒有重疊區域,例如下圖中紅圈所示的重疊線條,否則出現問題時難以定位錯誤提交:

Paste_Image.png
  • 查看本地分支與遠程倉庫master分支的差別,即本地分支對應的pull request包含的內容

    git log --oneline --left-right origin/master...<本地分支名稱>

    對于未與遠程倉庫master分支同步即rebase的分支:

    $ git log --oneline --left-right origin/master...feature/KTOS-573-add-i2c-subsystem-2
    < deb713e Merge pull request #568 to master
    > be27660 XXXX
    ...
    < a674652 XXXX
    ...
    > c1a52d3 XXXX
    ...
    

    其中,<代表僅存在于遠程分支上的提交,>代表僅存在于本地分支上的提交。而已經與遠程倉庫master分支同步即rebase的分支,則只包含>,即即僅存在于本地分支上的提交。

  • 查看某次提交中所有或某個文件的具體修改內容

    git show <提交ID> <可選文件路徑>

  • 查看文件的歷史版本

    git show <提交ID>:<文件路徑>

  • 查看某個文件中所有或指定行的修改記錄

    git blame <文件路徑>
    git blame -L <起始行>,<結束行> <文件路徑>
    git blame -L <起始行>,<+行數> <文件路徑>

3.2.3 查看本地倉庫的git操作記錄并無限回退

  • 查看操作記錄

    git reflog

Paste_Image.png
  • 回退到某次操作后的狀態

    git reset HEAD@{序號}

    注意

    • 沒有提到到倉庫中的代碼無法恢復;
    • 暫存區的代碼會受影響,如需要保留可先提交到本地倉庫進行備份。

3.3 分支

分支是指向提交的的可變指針(參見Git-分支-分支簡介),每個git倉庫都有一個默認創建的master分支和若干其他分支,支持如下常用操作:

3.3.1 查看分支信息

  • 查看本地分支信息

    git branch

    注意:當前分支名稱之前會有*標志。

  • 查看本地分支詳細信息

    git branch -v

Paste_Image.png
  • 查看包含分支標簽的本地倉庫日志

    git log --oneline --decorate

Paste_Image.png
  • 查看遠程倉庫分支信息

    git branch -r

Paste_Image.png
  • 查看所有分支(包含本地和遠程倉庫)信息

    git branch -a

Paste_Image.png

3.3.2 從當前分支到其他分支

  • 切換到本地倉庫或遠程倉庫已有分支

    git checkout <分支名稱>

  • 從當前分支創建一個新分支并切換到新分支

    git checkout -b <新分支名稱>

  • 從某個提交創建一個新分支并切換到新分支(用于查看內容或者查找問題)

    git checkout <提交ID> -b <新分支名稱>

  • 刪除某個分支

    git branch -D <分支名稱>

3.3.3 從其他分支到當前分支

  • 合并其他分支到當前分支,

    git merge <其他分支名稱>

    注意

    • 該操作有可能造成提交交錯,影響問題定位,因此不建議使用,除非你知道自己在干什么!!!
    • 如果合并過程中有沖突,需要順序執行如下操作:
      • 編輯沖突文件,或刪除不需要的文件;
      • 使用git add -u將修改添加到暫存區;
      • 使用git commit提交修改。
  • 終止當前合并操作

    git merge --abort

  • 將其他分支的某個提交合并到當前分支

    git cherry-pick <提交ID>

3.4 工作區和暫存區

工作區是工作目錄的形象化稱呼,實際上就是當前分支最新版本的本地副本;暫存區(stage)則是包含將要提交到本地倉庫中的文件的索引列表(參見Git權威指南-git暫存區)。

3.4.1 查看工作區和暫存區內容

  • 查看工作區中文件的修改內容,即比較工作區與暫存區中的文件

    git diff <可選路徑或文件名>

  • 查看暫存區中文件的修改內容,即比較暫存區與HEAD的文件

    git diff --cached <文件名>

  • 比較工作區與某個提交中的文件

    git diff <提交ID> <可選路徑或文件名>

  • 比較暫存區與某個提交中的文件

    git diff --cached <提交ID> <可選路徑或文件名>

  • 比較2個提交中的文件

    git diff <提交ID1> <提交ID2> <可選路徑或文件名>
    git diff --name-only <提交ID1> <提交ID2> <可選路徑或文件名>

    注意

    • 2個提交中必須包含對要比較的文件的修改,且提交ID1更舊;
    • --name-only用于只顯示文件名。

3.4.2 從工作區到暫存區

  • 將工作區中的所有或某個文件放到暫存區

    git add <文件或目錄路徑>

  • 將工作區中所有對倉庫中已有代碼的修改放到暫存區

    git add -u

  • 以交互方式暫存文件

    git add -i

    注意

    • 該操作可以每一個被修改的文件和被修改的文件中的每一處修改都作出是否提交到暫存區的選擇;
    • 詳細操作參見Git-工具-交互式暫存
  • 刪除文件和目錄

    git rm
    git rm -r

  • 移動文件和目錄

    git mv

3.4.3 從暫存區到工作區

  • 將暫存區中對倉庫中所有或某個文件的修改恢復到工作區

    git reset HEAD <可選的文件或目錄路徑>

3.4.4 從暫存區到本地倉庫

  • 將暫存區中的內容提交到本地倉庫(簡單注釋)

    git commit -m "注釋信息"

  • 將暫存區中的內容提交到本地倉庫(復雜注釋,將會進入文本編輯界面,默認使用vi)

    git commit

  • 修改上次提交的注釋信息

    git commit --amend -m "注釋信息"

3.4.5 從本地倉庫到暫存區即清除暫存區

  • 使用本地倉庫中某個提交的代碼覆蓋暫存區并更新HEAD指針

    git reset <提交ID>

    注意,工作區的內容不受影響,但是暫存區中未提交到本地倉庫中的修改會被覆蓋。

3.4.6 從本地倉庫到工作區

  • 使用本地倉庫中的最新代碼覆蓋工作區中的內容,即撤銷工作區內的所有或某個文件的修改

    git checkout .
    git checkout -- <文件或者目錄名>

    注意:本操作實質上是用本地倉庫中的數據覆蓋工作區中的內容。

  • 使用本地倉庫中某個提交的內容覆蓋工作區中的某個文件或所有內容

    git checkout <提交ID> <可選的文件或者目錄名>

  • 使用本地倉庫中某個提交的內容覆蓋工作區和暫存區并更新HEAD指針

    git reset --hard <提交ID>

3.4.7 從工作區到本地倉庫

  • 直接將文件提交到本地倉庫

    git commit -a -m "注釋信息"

    注意,該操作不經過暫存區,務必慎用!!!

3.4.8 清除工作區

  • 清除工作區

    git clean -fd

3.5 臨時緩沖區

臨時緩沖區(stash)是保存臨時修改內容的各個分支共享的全局緩沖區,支持如下常用操作(參見Git-工具-儲藏與清理):

3.5.1 查看臨時緩沖區

  • 顯示臨時緩沖區內保存的工作進度

    git stash list

    如下所示:

    $ git stash list
    stash@{0}: On bugfix/KTOS-499-pci-decouple: pci review
    

    其中,第1個:之前的部分是每個工作進度的標簽,2個:之間的部分是保存該工作進度時所在的分支,第2個:之后的部分是該工作進度的描述信息。

  • 顯示臨時緩沖區某個工作進度的內容

    git stash show stash@{序號}

3.5.2 從工作區和暫存區到臨時緩沖區

  • 將工作區和暫存區中對本地倉庫中已有代碼的修改備份到臨時緩沖區

    git stash save "緩沖區描述"

  • 將工作區和暫存區中的所有修改(包括不在本地倉庫中的文件)備份到臨時緩沖區

    git stash save -u "緩沖區描述"

3.5.3 從臨時緩沖區到工作區

  • 將臨時緩沖區中對倉庫中代碼的修改彈出到工作區

    git stash pop stash@{序號}

  • 將臨時緩沖區中對倉庫中代碼的修改應用到工作區(保留緩存區中的工作進度)

    git stash apply stash@{序號}

4. git進階

4.1 變基(參見Git權威指南-改變歷史

  • 該操作的基本語法為:

    git rebase --onto <目的提交> <起始提交> <結束提交>

  • 變基操作會為切換到 <目的提交>,然后把<起始提交>和<結束提交>之間的提交逐條疊加到<目的提交>之后;如果--onto <目的提交>未指定,則使用<起始提交>;如果<結束提交>未指定,則使用當前分支;

  • 變基操作通常用于當前任務分支跟主線同步,例如git rebase master

  • 變基操作中出現問題時,需要根據對沖突的文件提示進行修改,完成后使用git add -u提交到暫存區,并使用git rebase --continue繼續或git rebase --skip跳過當前提交繼續同步;

  • 變基操作可以被git rebase --abort終止以恢復到操作前狀態;

  • 變基操作結束以后,推送到服務器時,如果報錯,需要使用git push --force強制推送。

  • 如果修改內容較多,且長時間未同步,可能會出現同一文件多次沖突,因此強烈建議打開Rerere功能:

    git config --global rerere.enabled true

    使能后,沖突解決方案會被記錄,并在再次遇到時自動應用,不需要再吃手工編輯文件解決,只需要git add -u即可。

4.2 二分法查找錯誤版本(參考Git權威指南-二分查找

該方法用于快速定位問題,但是需要如下條件作為前提才能高效工作:

  • 提交線性排序,不存在下圖所示的重疊部分:
Paste_Image.png
  • 每個關鍵提交最好都能編譯通過或運行。

該操作具體步驟如下(使用簡單實例,具體使用時根據需要調整):

  • 查看當前日志

    $ git log --oneline**
    ebc659b second bad
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    
  • 啟動查找

    $ git bisect start
    
  • 標志當前版本為壞版本

    $ git bisect bad
    
  • 標志某個好版本作為起點

    $  git bisect good 84ec8c3
    Bisecting: 0 revisions left to test after this (roughly 1 step)
    [2fe7f29987123abe3fa0cb3429c07b597f86594c] first bad
    

    此時會自動跳轉到中間版本:

    $ git log --oneline
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    
  • 如果當前版本為壞版本,標志他

    $ git bisect bad
    Bisecting: 0 revisions left to test after this (roughly 0 steps)
    [abfcfbc361beb42551b4219d6d70ccb1fe3ac103] second good
    

    此時會自動跳轉到中間版本:

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 如果當前版本為好版本,標志他

    $ git bisect good
    2fe7f29987123abe3fa0cb3429c07b597f86594c is the first bad commit
    commit 2fe7f29987123abe3fa0cb3429c07b597f86594c
    Author: Matt Zu<matt.zu@pc.com>
    Date:   Tue Dec 20 20:36:56 2016 +0800
        first bad
    :100644 100644 0cfbf08886fca9a91cb753ec8734c84fcbe52c9f c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 M      test.c
    

    找到第一個壞版本時,自動結束,不再跳轉到中間版本:

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 切換到第一個壞版本

    $ git checkout bisect/bad
    Previous HEAD position was abfcfbc... second good
    HEAD is now at 2fe7f29... first bad
    

    日志如下:

    $ git log --oneline
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    

4.3 壓縮提交(參見Git-工具-重置揭密#壓縮

每個pull request中應當包含盡可能少的提交,因此在推送到服務器之前,每個功能點或者修改點包含的所有提交都應當壓縮成一個提交,并編譯通過,最好能夠通過基本測試。

該操作具體步驟如下(使用簡單實例,具體使用時根據需要調整):

  • 查看當前日志

    $ git log --oneline
    f0fd7c9 commit msg 2
    335067c commit msg 1
    abfcfbc second good
    84ec8c3 first good
    
  • 查看文件修改記錄

    $ git blame test.c
    abfcfbc3 (Matt Zu 2016-12-20 20:36:35 +0800 1) 2
    335067c5 (Matt Zu 2016-12-27 14:28:33 +0800 2) 3
    f0fd7c9b (Matt Zu 2016-12-27 14:28:48 +0800 3) 4
    
  • 將HEAD指針回退到需要合并的提交之前

    $ git reset --soft 335067c^
    

注意^用于回退到上一次提交,等價于~1;也可以疊加使用以回退到N次提交之前,等價于~N

  • 查看日志

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改內容

    $ git status
    On branch msg
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   test.c
    $ git diff --cached
    diff --git a/test.c b/test.c
    index 0cfbf08..dcf37cd 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
     2
    +3
    +4
    
  • 再次提交代碼以合并提交

    git commit -m "combine commit msg"
    
  • 查看日志

    $ git log --oneline
    a1fadaf combine commit msg
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改內容

    $ git log --oneline -p -1
    a1fadaf combine commit msg
    diff --git a/test.c b/test.c
    index 0cfbf08..dcf37cd 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
     2
    +3
    +4
    

4.4 拆分提交(參見Git-工具-重寫歷史#拆分提交

該操作用于對不合理的提交壓縮進行拆分,以方便cherry-pick和二分法查找等后續操作。

注意:該操作也可以用于調整提交的順序,參見Git-工具-重寫歷史#重新排序提交

該操作具體步驟如下(使用簡單實例,具體使用時根據需要調整):

  • 查看日志

    $ git log --oneline
    0b22507 add aditional number
    abc373f update number and insert lines
    abfcfbc second good
    84ec8c3 first good
    

    假定abc373f為需要拆分的提交。

  • 查看修改內容

    $ git log --oneline -p -2
    0b22507 add aditional number
    diff --git a/test.c b/test.c
    index 2ff46c8..ab7998f 100644
    --- a/test.c
    +++ b/test.c
    @@ -1,3 +1,3 @@
    
    -3
    +3 4 5
    
    abc373f update number and insert lines
    diff --git a/test.c b/test.c
    index 0cfbf08..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    -2
    +
    +3
    +
    
  • 變基到需要拆分的提交(abc373f)之前

    $ git rebase -i abc373f^
    

    此時會進入vim界面,顯示如下內容:

    pick abc373f update number and insert lines
    pick 0b22507 add aditional number
    
    # Rebase abfcfbc..0b22507 onto abfcfbc (2 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
    #
    # 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
    ~
    

    根據提示,將需要拆分的提交前面的pick修改為edit此處可以調整提交順序):

    edit abc373f update number and insert lines
    pick 0b22507 add aditional number
    

    然后保存并退出,顯示如下提示:

    $ git rebase -i abc373f^
    warning: Stopped at abc373f... update number and insert lines
    You can amend the commit now, with
    
      git commit --amend
    
    Once you are satisfied with your changes, run
    
      git rebase --continue
    
  • 查看日志

    $ git log --oneline
    abc373f update number and insert lines
    abfcfbc second good
    84ec8c3 first good
    
  • 回退HEAD指針到上一次提交

    $ git reset HEAD^
    Unstaged changes after reset:
    M       test.c
    
  • 查看修改內容

    $ git diff
    diff --git a/test.c b/test.c
    index 0cfbf08..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    -2
    +
    +3
    +
    
  • 將修改內容保存到臨時緩沖區

    $ git stash save "msg split"
    Saved working directory and index state On (no branch): msg split
    HEAD is now at abfcfbc second good
    
  • 將修改內容應用到工作區并保留緩沖區中的進度

    $ git stash apply stash@{0}
    
  • 移除不需要的修改并提交(此處僅保留數字更新)

    $ git diff
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    $ git add -u
    $ git commit -m "update number"
    [detached HEAD c2b7f71] update number
     1 file changed, 1 insertion(+), 1 deletion(-)
    
  • 查看日志

    $ git log --oneline
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改內容

    $ git log --oneline -p -1
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    
  • 將修改內容彈出到工作區,修改沖突后再次提交

    $ git stash pop stash@{0}
    Auto-merging test.c
    CONFLICT (content): Merge conflict in test.c
    Recorded preimage for 'test.c'
    $ vim test.c
    $ git commit -m "insert lines"
    Recorded resolution for 'test.c'.
    [detached HEAD 13a6963] insert lines
     1 file changed, 2 insertions(+)
    
  • 查看日志

    $ git log --oneline
    13a6963 insert lines
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改內容

    $ git log --oneline -p -2
    13a6963 insert lines
    diff --git a/test.c b/test.c
    index 00750ed..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    +
     3
    +
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    
  • 繼續變基

    $ git rebase --continue
    Successfully rebased and updated refs/heads/msg_split.
    
  • 查看日志

    $ git log --oneline
    dc4e8fa add aditional number
    13a6963 insert lines
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改內容

    $ git log --oneline -p -3
    dc4e8fa add aditional number
    diff --git a/test.c b/test.c
    index 2ff46c8..ab7998f 100644
    --- a/test.c
    +++ b/test.c
    @@ -1,3 +1,3 @@
    
    -3
    +3 4 5
    
    13a6963 insert lines
    diff --git a/test.c b/test.c
    index 00750ed..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    +
     3
    +
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    

4.5 補丁操作(參見分布式-Git-向一個項目貢獻#r_project_over_email分布式 Git - 維護項目

該操作用于創建和應用patch。

  1. 標準格式補丁創建

    每個標準格式補丁就是1個包含提交消息、修改文件概述和修改文件細節的mbox格式文件:

    $ cat 0001-test1.patch
    From 0d57e1ea1a27c54c7ec62cacfccb7d037923150a Mon Sep 17 00:00:00 2001
    From: matt <matt@pc.com>
    Date: Mon, 28 May 2018 16:29:57 +0800
    Subject: [PATCH 1/2] test1
    
    ---
     README | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    !!!此處可以增加自定義信息以方便閱讀,應用補丁時會被忽略。!!!
    
    diff --git a/README b/README
    index df1d5d6..3409f8c 100644
    --- a/README
    +++ b/README
    @@ -5,7 +5,7 @@
    
     Summary:
     ========
    -
    +1111111111111111111111111111111
     This directory contains the source code for U-Boot, a boot loader for
     Embedded boards based on PowerPC, ARM, MIPS and several other
     processors, which can be installed in a boot ROM and used to
    --
    2.10.1.windows.1
    

    操作命令如下所示:

    • git format-patch -M master

      為主線上不存在的每個提交創建一個標準格式補丁文件,同時查找重命名操作。注意,該操作需要切換到當前工作分支,并與主線同步后執行,即git checkout <工作分支>git rebase master之后。

    • git format-patch <起始提交ID或者標簽>...<結束提交ID或者標簽>

      為當前分支上起始提交ID或者標簽與結束提交ID或者標簽之間的每個提交創建一個標準格式補丁文件,不包括起始提交ID或者標簽,但是包含結束提交ID或者標簽。

      注意:

      • --cover-letter選項用于創建郵一個額外的mbox格式文件,包含所有提交的信息,而不只是某一個提交的信息。
        $ cat 0000-cover-letter.patch
        From 89d4c523ebf5bb6c700bcbf8e2c899c3f1d345fe Mon Sep 17 00:00:00 2001
        From: matt <matt@pc.com>
        Date: Tue, 29 May 2018 09:28:44 +0800
        Subject: [PATCH 0/2] *** SUBJECT HERE ***
        
        *** BLURB HERE ***
        
        matt (2):
          test1
          test2
        
         README | 2 +-
         1 file changed, 1 insertion(+), 1 deletion(-)
        
        --
        2.10.1.windows.1
        
      • 結束提交ID或者標簽可以省略,默認為HEAD
    • git am <標準格式補丁文件>

      從標準格式補丁文件中讀取補丁內容并應用到當前分支。注意,補丁文件應用沖突時,該操作會停下來,提示手工解決沖突,并在沖突解決后使用git am --resolved繼續應用下一個補丁:

      $ vim README
      $ git add ticgit.gemspec
      $ git am --resolved
      Applying: test1
      

      當然,也可以跳過(git am --skip)或者終止(git am --abort)本次操作。

  2. diff格式補丁

    diff格式補丁使用diff命令創建,就是一個包含修改內容的文本文件,不包含提交消息和修改文件概述,但是可已經將多個提交的修改合并到一個文件中,方便閱讀,但是應用補丁時只有補丁內容全部應用和完全不應用兩種可能

    $ cat patch.txt
    diff --git a/README b/README
    index df1d5d6..3409f8c 100644
    --- a/README
    +++ b/README
    @@ -5,7 +5,7 @@
    
     Summary:
     ========
    -
    +1111111111111111111111111111111
     This directory contains the source code for U-Boot, a boot loader for
     Embedded boards based on PowerPC, ARM, MIPS and several other
     processors, which can be installed in a boot ROM and used to
    
    • git diff -c -p <起始提交ID或者標簽>...<結束提交ID或者標簽> > <補丁文件名稱>

      將當前分支上起始提交ID或者標簽與結束提交ID或者標簽之間的所有修改創建一個diff格式補丁,不包括起始提交ID或者標簽,但是包含結束提交ID或者標簽。注意結束提交ID或者標簽可以省略,默認為HEAD,例如:

      git diff -c -p HEAD^ > patch.txt

    • git apply <補丁文件名稱>

      讀取補丁內容并應用到當前分支。注意,本操作只修改當前分支文件,不會自動創建提交。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容