04_Git工具

Git工具

選擇修訂版本

Git能夠以多種方式來(lái)指定單個(gè)提交、一組提交或者是一定范圍內(nèi)的提交。

單個(gè)修訂版本

可以通過(guò)任意一個(gè)提交時(shí)生成的40個(gè)字符的完整SHA-1散列值來(lái)指定一個(gè)提交。

簡(jiǎn)短的SHA-1

通常,Git中,使用一部分的SHA-1散列值就能夠唯一確定一個(gè)提交記錄,我們?cè)?code>git log中加上--abbrev-commit選項(xiàng)就可以為每一個(gè)提交顯示簡(jiǎn)短的唯一散列值。例如

$ git log --abbrev-commit --pretty=oneline
67520cb (HEAD -> master) 新建一個(gè)hello.c文件

分支引用

  1. 我們還可以直接使用分支名來(lái)指定一個(gè)提交記錄,這時(shí)候,分支名指定的記錄就是分支指針當(dāng)前指向的最新提交記錄。例如

    $ git show master
    commit 67520cb3fac87c26c2eb11b501c151c993b95c30 (HEAD -> master)
    Author: Square John <1042009398@qq.com>
    Date:   Sat May 30 16:37:20 2020 +0800
    
        新建一個(gè)hello.c文件
    
    diff --git a/.gitignore b/.gitignore
    new file mode 100644
    index 0000000..3110669
    --- /dev/null
    +++ b/.gitignore
    @@ -0,0 +1 @@
    +a.exe
    \ No newline at end of file
    diff --git a/hello.c b/hello.c
    new file mode 100644
    index 0000000..852836c
    --- /dev/null
    +++ b/hello.c
    @@ -0,0 +1,7 @@
    +#include <stdio.h>
    +
    +int main(void){
    +
    +       printf("Hello World\n");
    +       return 0;
    +}
    
  1. 我們還可以使用rev-parse工具獲取一個(gè)分支當(dāng)前所指向的提交記錄的SHA-1值。例如

    $ git rev-parse master
    67520cb3fac87c26c2eb11b501c151c993b95c30
    

引用日志

  1. 當(dāng)我們?cè)诠ぷ鲿r(shí),Git會(huì)在后臺(tái)保存一個(gè)引用日志(==reflog==),引用日志保存了我們近幾個(gè)月來(lái)的==HAED==和分支指針?biāo)赶虻臍v史。因此我們可以使用git reflog來(lái)查看引用日志,例如

    $ git reflog
    67520cb (HEAD -> master) HEAD@{0}: commit (initial): 新建一個(gè)hello.c文件
    
  1. 每當(dāng)我們的==HEAD==指針的指向發(fā)生了變化,Git就會(huì)將這個(gè)信息存儲(chǔ)在引用日志這個(gè)歷史記錄里。我們可以通過(guò)引用日志數(shù)據(jù)來(lái)獲取之前的提交歷史。

  2. 如果我們想要查看HEAD最近的5次之前所指向的提交記錄(也就是倒著往回?cái)?shù)第6次的提交記錄,我們可以使用@{5}來(lái)引用reflog中輸出的提交記錄。例如

    $ git reflog
    a5d2b56 (HEAD -> master) HEAD@{0}: commit: 添加一行'Hello C'
    b1fc8a9 HEAD@{1}: commit: 將換行符作為單獨(dú)一行輸出
    67520cb HEAD@{2}: commit (initial): 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git show HEAD@{1}
    commit b1fc8a98292d9a97d786732d3fa575475348f5f9
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 09:44:57 2020 +0800
    
        將換行符作為單獨(dú)一行輸出
    
    diff --git a/hello.c b/hello.c
    index 852836c..e04f5f2 100644
    --- a/hello.c
    +++ b/hello.c
    @@ -2,6 +2,7 @@
    
     int main(void){
    
    -       printf("Hello World\n");
    +       printf("Hello World");
    +       printf("\n);
            return 0;
     }
    
    • 該命令實(shí)際上就是輸出reflog日志中的相應(yīng)的第HEAD@{n}次記錄
  3. 我們同樣可以使用這樣的語(yǔ)法來(lái)查看某一個(gè)分支在指定時(shí)間前的位置。例如

    $ git show master@{yesterday}
    warning: log for 'master' only goes back to Sat, 30 May 2020 16:37:20 +0800
    commit 67520cb3fac87c26c2eb11b501c151c993b95c30
    Author: Square John <1042009398@qq.com>
    Date:   Sat May 30 16:37:20 2020 +0800
    
        新建一個(gè)hello.c文件
    
    diff --git a/.gitignore b/.gitignore
    new file mode 100644
    index 0000000..3110669
    --- /dev/null
    +++ b/.gitignore
    @@ -0,0 +1 @@
    +a.exe
    \ No newline at end of file
    diff --git a/hello.c b/hello.c
    new file mode 100644
    index 0000000..852836c
    --- /dev/null
    +++ b/hello.c
    @@ -0,0 +1,7 @@
    +#include <stdio.h>
    +
    +int main(void){
    +
    +       printf("Hello World\n");
    +       return 0;
    +}
    
  1. 可以使用git log -g來(lái)查看類似于git log輸出格式的引用日志信息。例如

    $ git log -g master
    commit a5d2b563e6ffa56ef36383d4a1eb7bb5b690d1a1 (HEAD -> master)
    Reflog: master@{0} (Square John <1042009398@qq.com>)
    Reflog message: commit: 添加一行'Hello C'
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 09:49:11 2020 +0800
    
        添加一行'Hello C'
    
    commit b1fc8a98292d9a97d786732d3fa575475348f5f9
    Reflog: master@{1} (Square John <1042009398@qq.com>)
    Reflog message: commit: 將換行符作為單獨(dú)一行輸出
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 09:44:57 2020 +0800
    
        將換行符作為單獨(dú)一行輸出
    
    commit 67520cb3fac87c26c2eb11b501c151c993b95c30
    Reflog: master@{2} (Square John <1042009398@qq.com>)
    Reflog message: commit (initial): 新建一個(gè)hello.c文件
    Author: Square John <1042009398@qq.com>
    Date:   Sat May 30 16:37:20 2020 +0800
    
        新建一個(gè)hello.c文件
    
    • 如果不指定后面的分支名,就默認(rèn)為輸出當(dāng)前分支的引用日志信息
  2. 注意

    • 引用日志只存在于本地倉(cāng)庫(kù),它只是一個(gè)記錄我們?cè)谧约旱膫}(cāng)庫(kù)里做過(guò)什么的日志
    • 其他人拷貝的倉(cāng)庫(kù)里的引用日志不會(huì)和我們的相同
    • 如果我們剛剛新克隆了一個(gè)倉(cāng)庫(kù),那么我們克隆所得的本地庫(kù)中的引用日志是空的,因?yàn)槲覀冊(cè)谶@個(gè)倉(cāng)庫(kù)里面還沒(méi)有任何操作
    • git show HEAD@{two.month.ago}這一條命令只有當(dāng)我們的本地倉(cāng)庫(kù)至少已經(jīng)存在了兩個(gè)月才能夠顯示匹配的提交

祖先引用

  1. 祖先引用是另一種指明一個(gè)提交的方式。

  2. 如果我們?cè)谝玫暮竺婕由弦粋€(gè)^(脫字符),Git就會(huì)將其解析為該引用的上一個(gè)提交。例如

    $ git log --oneline
    a5d2b56 (HEAD -> master) 添加一行'Hello C'
    b1fc8a9 將換行符作為單獨(dú)一行輸出
    67520cb 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git show HEAD^
    commit b1fc8a98292d9a97d786732d3fa575475348f5f9
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 09:44:57 2020 +0800
    
        將換行符作為單獨(dú)一行輸出
    
    diff --git a/hello.c b/hello.c
    index 852836c..e04f5f2 100644
    --- a/hello.c
    +++ b/hello.c
    @@ -2,6 +2,7 @@
    
     int main(void){
    
    -       printf("Hello World\n");
    +       printf("Hello World");
    +       printf("\n);
            return 0;
     }
    
    • 結(jié)果就是==b1fc8a9 將換行符作為單獨(dú)一行輸出==這一個(gè)提交記錄
  3. 在==Windows==的cmd^是一個(gè)特殊字符,應(yīng)該這樣做

    $ git show HEAD^ #error
    $ git show "HEAD^" #ok
    $ git show HEAD^^ #ok
    
  1. 我們還可以在^后面跟上一個(gè)數(shù)字指明我們想要的父提交。但是這種做法只適用于有多個(gè)父提交合并提交。例如

    $ git log --oneline --graph --all
    *   25dd4cc (HEAD -> master) Merge branch 'newbranch'
    |\
    | * 35241b9 (newbranch) 為readme文件新增了一行
    * | 14e9ff1 刪除了打印hello world這一行
    |/
    * 2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
    * 62ed47d 新增一個(gè)readme文件
    * a5d2b56 添加一行'Hello C'
    * b1fc8a9 將換行符作為單獨(dú)一行輸出
    * 67520cb 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git show HEAD^2
    commit 35241b91e2957c7dc9c22b47f0c394d473215c3a (newbranch)
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 10:43:26 2020 +0800
    
        為readme文件新增了一行
    
    diff --git a/readme b/readme
    index b34569e..6638245 100644
    --- a/readme
    +++ b/readme
    @@ -1 +1,2 @@
     這是一個(gè)說(shuō)明文檔
    +用于說(shuō)明一些問(wèn)題
    
    • HEAD^2就是newbranch中的==35241b9==這一個(gè)提交記錄,也就是HEAD的第二個(gè)父提交
  2. 另一種指明祖先提交的方法是在引用的后面加一個(gè)~號(hào),HEAD~HEAD^一樣,都是指向HEAD的第一個(gè)父提交。但是HEAD~2表示的卻是HEAD的第一個(gè)父提交的第一個(gè)父提交。對(duì)于HEAD~3,那就是HEAD的第一個(gè)父提交的第一個(gè)父提交的父提交,其余以此類推。其實(shí)HEAD~3也可以這樣表示HEAD~~~

  3. ^~還可以進(jìn)行組合。例如HEAD~2^2就表示HEAD的第一個(gè)父提交的第一個(gè)父提交的第二個(gè)父提交

提交區(qū)間

雙點(diǎn)
  1. 最常用的指明提交區(qū)間的語(yǔ)法是雙點(diǎn),這種語(yǔ)法可以選出在一個(gè)分支中但是不在另一個(gè)分支中的提交歷史

  2. 例如

    $ git log --graph --oneline --all
    * 7c3bc83 (HEAD -> master) 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    *   25dd4cc Merge branch 'newbranch'
    |\
    * | 14e9ff1 刪除了打印hello world這一行
    | | * 95302bd (newbranch) 在readme末尾新加了一行說(shuō)明
    | |/
    | * 35241b9 為readme文件新增了一行
    |/
    * 2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
    * 62ed47d 新增一個(gè)readme文件
    * a5d2b56 添加一行'Hello C'
    * b1fc8a9 將換行符作為單獨(dú)一行輸出
    * 67520cb 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git log --oneline master..newbranch
    95302bd (newbranch) 在readme末尾新加了一行說(shuō)明
    
    • 這個(gè)命令選出了在newbranch分支中但是還沒(méi)有合并到master分支中的提交歷史記錄
    • 這樣的語(yǔ)法可以幫助我們即使了解分支的最新情況,以及將要合并的內(nèi)容
  3. 這個(gè)語(yǔ)法的另外一個(gè)常用的場(chǎng)景就是用于查看我們將要推送到遠(yuǎn)方的內(nèi)容

    $ git log origin/master..HEAD
    
    • 這個(gè)命令會(huì)輸出在我們當(dāng)前的分支但是不在origin/master分支的提交歷史
    • 如果我們執(zhí)行git push命令,并且我們當(dāng)前的分支正在跟蹤origin/master分支,則上面的命令所輸出的提交內(nèi)容就是我們將要提交的內(nèi)容
    • 如果我們留空了其的一邊,Git會(huì)默認(rèn)為HEAD,例如git log origin/master..,那么我們也會(huì)得到和上面一致的結(jié)果。Git會(huì)使用HEAD來(lái)代替留空的一邊
多點(diǎn)
  1. ? 有時(shí)候我們需要兩個(gè)以上的分支才能確定我們所需要的修訂。比如查看哪些提交是被包含在某些分支中的一個(gè),但是不在當(dāng)前的分支上

  2. Git有這樣的語(yǔ)法,在任意引用前加上一個(gè)^或者是--not用來(lái)指明不包含在指定分支中的提交。例如

    $ git log --oneline --all --graph
    * 7c3bc83 (master) 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    *   25dd4cc Merge branch 'newbranch'
    |\
    * | 14e9ff1 刪除了打印hello world這一行
    | | * 95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    | |/
    | * 35241b9 為readme文件新增了一行
    |/
    * 2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
    * 62ed47d 新增一個(gè)readme文件
    * a5d2b56 添加一行'Hello C'
    * b1fc8a9 將換行符作為單獨(dú)一行輸出
    * 67520cb 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (newbranch)
    $ git log --oneline master..newbranch
    95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    
    helloworld@surface MINGW64 ~/Desktop/cpl (newbranch)
    $ git log --oneline ^master newbranch
    95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    
    helloworld@surface MINGW64 ~/Desktop/cpl (newbranch)
    $ git log --oneline newbranch --not master
    95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    
    • 其中這三條命令是等價(jià)的

      $ git log --oneline master..newbranch
      $ git log --oneline ^master newbranch
      $ git log --oneline newbranch --not master
      
      • 列出的都是在newbranch中但是不在master中的提交歷史
    • 但是注意,下面這兩個(gè)命令是不一樣的

      $ git log --oneline newbranch --not master
      $ git log --oneline --not master newbranch
      
      • 前者是指,包含在newbranch中但是不包含在master中的提交記錄
      • 后者是不包含在newbranch以及master中的記錄
    • 但是下面這兩個(gè)命令是一樣的

      $ git log --oneline ^master newbranch
      $ git lig --oneline newbranch ^master
      
      • 都是不在master中但是在newbranch中的提交記錄
    • 也就是說(shuō),--not是對(duì)其后所有的分支的否定,就是其后的分支都不包含的提交記錄。而^只是對(duì)其后緊接著的一個(gè)分支的否定。

  3. 這樣的語(yǔ)法就可以這樣使用

    $ git log --oneline ba bb ^bc
    
    • 這就表示,包含在babb中但是不包含在bc中的提交記錄
三點(diǎn)
  1. 這個(gè)語(yǔ)法可以可以選擇出被兩個(gè)引用之一包含但是又不同時(shí)被二者包含的提交歷史

  2. 例子如下

    $ git log --oneline master...newbranch
    7c3bc83 (master) 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    25dd4cc Merge branch 'newbranch'
    14e9ff1 刪除了打印hello world這一行
    
    • 該命令就列出了所有只在master或者是newbranch分支中的其中一個(gè)的所有的提交記錄
  3. 在該命令中添加--left-right選項(xiàng)能夠顯示每一個(gè)提交所屬的分支,這會(huì)讓輸出數(shù)據(jù)更加清晰。例如

    $ git log --oneline --graph --all
    * 7c3bc83 (master) 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    *   25dd4cc Merge branch 'newbranch'
    |\
    * | 14e9ff1 刪除了打印hello world這一行
    | | * 95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    | |/
    | * 35241b9 為readme文件新增了一行
    |/
    * 2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
    * 62ed47d 新增一個(gè)readme文件
    * a5d2b56 添加一行'Hello C'
    * b1fc8a9 將換行符作為單獨(dú)一行輸出
    * 67520cb 新建一個(gè)hello.c文件
    
    helloworld@surface MINGW64 ~/Desktop/cpl (newbranch)
    $ git log --oneline --left-right master...newbranch
    < 7c3bc83 (master) 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    > 95302bd (HEAD -> newbranch) 在readme末尾新加了一行說(shuō)明
    < 25dd4cc Merge branch 'newbranch'
    < 14e9ff1 刪除了打印hello world這一行
    

交互式暫存

  1. 本節(jié)的幾個(gè)交互式Git可以幫助我們將文件的特定部分組合成提交。當(dāng)我們修改了大量文件之后,希望將這些改動(dòng)能夠拆分為若干個(gè)單獨(dú)的提交而不是混雜在一起成為一個(gè)提交時(shí),這些工具特別有用。

  2. 在運(yùn)行git add時(shí)使用-i或者--interactive選項(xiàng),Git會(huì)進(jìn)入一個(gè)交互式終端模式。如下所示

    $ git status
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   hello.c
            modified:   readme
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            multipleAB.c
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git add -i
               staged     unstaged path
      1:    unchanged        +0/-3 hello.c
      2:    unchanged        +1/-0 readme
    
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    What now>
    
    • 該命令會(huì)將已經(jīng)進(jìn)行了跟蹤的文件列出來(lái)分為兩列,其中一列為已暫存狀態(tài)的內(nèi)容的變化(就是對(duì)比本地庫(kù)和暫存區(qū)中的對(duì)應(yīng)文件差別),另外一列為為暫存狀態(tài)的內(nèi)容的變化(也就是對(duì)比工作區(qū)和暫存區(qū)中相應(yīng)的文件的差異)
    • 然后我可以使用==Commdans==下面的命令交互式地對(duì)文件進(jìn)行操作

文件的暫存和取消暫存

  1. 如果我們?cè)?=What now>==之后輸入==2==或者是==u==或者是==update==,接下來(lái)就會(huì)出現(xiàn)如下界面

    What now> 2
               staged     unstaged path
      1:    unchanged        +0/-3 hello.c
      2:    unchanged        +1/-0 readme
    Update>>
    
    • 這時(shí)候它問(wèn)我們需要暫存哪些文件
  2. 加入我們輸入如下,然后就會(huì)

    Update>> 1,2
               staged     unstaged path
    * 1:    unchanged        +0/-3 hello.c
    * 2:    unchanged        +1/-0 readme
    Update>>
    
    • 前面打上了==*****==號(hào)的文件表示將要被暫存的文件
  3. 如果我們?cè)?=Update>>==之后什么也不輸入而是直接回車,就會(huì)把前面帶有==*****==號(hào)的文件進(jìn)行暫存,接著界面就變成下面這樣

    updated 2 paths
    
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    What now>
    
  1. 加入我們這個(gè)時(shí)候想要撤銷對(duì)readme文件的暫存,我們可以輸入==3==或者是==r[evert]==。如下所示

    What now> 3
               staged     unstaged path
      1:        +0/-3      nothing hello.c
      2:        +1/-0      nothing readme
    Revert>>
    
  1. 這時(shí)候我們就可以選擇要撤銷暫存的文件

    Revert>> 2
               staged     unstaged path
      1:        +0/-3      nothing hello.c
    * 2:        +1/-0      nothing readme
    Revert>>
    
    • 此時(shí)前面帶有==*****==號(hào)的文件表示將要撤銷暫存的文件
  2. 和前面一樣,直接回車就可以將上面選擇的文件撤銷暫存

    Revert>>
    reverted 1 path
    
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    What now>
    
  1. 然后選擇==1==或者是==s[tatus]==就可以查看這些已被追蹤文件的狀態(tài)

    What now> s
               staged     unstaged path
      1:        +0/-3      nothing hello.c
      2:    unchanged        +1/-0 readme
    
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    What now>
    
  1. 然后選擇==6==或者是==d[iff]==就可以查看本地庫(kù)中的文件和暫存區(qū)中相應(yīng)的文件的差異,該命令和git diff --cached效果一樣。首先是出現(xiàn)如下界面,讓我們選擇需要進(jìn)行對(duì)比的文件

    What now> 6
               staged     unstaged path
      1:        +0/-3      nothing hello.c
    Review diff>>
    
  1. 然后我們選擇==1==,結(jié)果如下

    Review diff>> 1
    diff --git a/hello.c b/hello.c
    index 0384c93..1f84282 100644
    --- a/hello.c
    +++ b/hello.c
    @@ -3,8 +3,5 @@
     int main(void){
    
            printf("Hello C\n");
    -       int a = 10;
    -       int b = 20;
    -       printf("%d + %d = %d\n", a, b, a + b);
            return 0;
     }
    *** Commands ***
      1: status       2: update       3: revert       4: add untracked
      5: patch        6: diff         7: quit         8: help
    What now>
    
  1. 然后選擇==7==或者==q[uit]==退出交互式界面

暫存補(bǔ)丁

  1. 如果我們一個(gè)文件的多個(gè)地方進(jìn)行了修改,但是我們只想要暫存其中的一個(gè)修改,那么這個(gè)Git也能輕松做到

  2. 在上一節(jié)的交互式命令中,選擇==5==或者是==p[atch]==,然后就會(huì)進(jìn)入如下的選擇界面

    What now> 5
    warning: LF will be replaced by CRLF in multipleAB.c.
    The file will have its original line endings in your working directory
               staged     unstaged path
      1:    unchanged        +5/-3 multipleAB.c
      2:    unchanged        +2/-0 readme
    Patch update>>
    
  1. 然后選擇相應(yīng)的文件,如下所示

    Patch update>> 2
               staged     unstaged path
      1:    unchanged        +5/-3 multipleAB.c
    * 2:    unchanged        +2/-0 readme
    Patch update>>
    
  2. 然后回車,進(jìn)入如下界面

    Patch update>>
    diff --git a/readme b/readme
    index 6638245..7cbb288 100644
    --- a/readme
    +++ b/readme
    @@ -1,2 +1,4 @@
     這是一個(gè)說(shuō)明文檔
     用于說(shuō)明一些問(wèn)題
    +就是想添加一行文字
    +又添加一行文字
    (1/1) Stage this hunk [y,n,q,a,d,e,?]?
    
  1. 然后輸入==?==回車就可以看到各個(gè)選項(xiàng)的意義

    (1/1) Stage this hunk [y,n,q,a,d,e,?]? ?
    y - stage this hunk
    n - do not stage this hunk
    q - quit; do not stage this hunk or any of the remaining ones
    a - stage this hunk and all later hunks in the file
    d - do not stage this hunk or any of the later hunks in the file
    e - manually edit the current hunk
    ? - print help
    @@ -1,2 +1,4 @@
     這是一個(gè)說(shuō)明文檔
     用于說(shuō)明一些問(wèn)題
    +就是想添加一行文字
    +又添加一行文字
    (1/1) Stage this hunk [y,n,q,a,d,e,?]?
    
  1. 然后我們可以選擇==y==暫存這部分內(nèi)容,隨后就可以使用==1==來(lái)查看文件的狀態(tài)

  2. 實(shí)際上上面這個(gè)功能可以通過(guò)git add --patch/-p啟動(dòng)

貯藏和清理

  1. 有時(shí)候我們可能會(huì)在某一個(gè)分支上進(jìn)行了一些工作,做了一些修改,然后想要切換到另外一個(gè)分支進(jìn)行一點(diǎn)工作,但是這個(gè)時(shí)候我們不想要將這些部分的還未完成的工作進(jìn)行提交,我們可以使用git stash命令
  2. 貯藏(stash)會(huì)處理工作目錄的臟的狀態(tài),即跟蹤文件的修改和暫存文件的改動(dòng),然后將未完成的修改保存到一個(gè)棧上,隨后我們還可以重新應(yīng)用這些改動(dòng)

貯藏工作

  1. 先在工作目錄中修改幾個(gè)文件,然后暫存其中的一個(gè),使用git status查看當(dāng)前倉(cāng)庫(kù)的狀態(tài)

    $ git status
    On branch master
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
            modified:   newfile
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   readme
    
  1. 將新的修改推送到棧上貯藏,使用git stash或者是git stash push命令

    $ git stash
    Saved working directory and index state WIP on master: d414efe 新建了一個(gè)newile文件,并在其中輸入了一行文字
    
    • 這時(shí)候會(huì)輸出改動(dòng)的內(nèi)容
  2. 然后我們?cè)诓榭磦}(cāng)庫(kù)的狀態(tài)

    $ git status
    On branch master
    nothing to commit, working tree clean
    
    • 我們可以看到,倉(cāng)庫(kù)目錄狀態(tài)是干凈的
  3. 然后我們就可以切換到其他分支上工作了。而如果我們想要查看貯藏的東西,可以執(zhí)行git stash list命令

    $ git stash list
    stash@{0}: WIP on master: d414efe 新建了一個(gè)newile文件,并在其中輸入了一行文字
    
  1. 使用git stash apply命令重新應(yīng)用貯藏

    $ git stash apply
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   newfile
            modified:   readme
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
  1. 如果想要應(yīng)用一個(gè)更舊版本的貯藏,可以使用它的名字指定它,例如git stash apply stash@{2}。如果不指定,就默認(rèn)使用最新版的貯藏

  2. 貯藏的內(nèi)容并不一定要應(yīng)用到進(jìn)行貯藏的分支,也不要求應(yīng)用貯藏時(shí)候的目錄是干凈的。但是如果這時(shí)候修改的是剛剛才修改了的文件,這時(shí)候會(huì)產(chǎn)生合并沖突。

  3. 我們從上面的結(jié)果可以看到貯藏被重新應(yīng)用了,但是剛才暫存的文件的內(nèi)容被恢復(fù)了但是沒(méi)有被重新暫存

  4. 如果我們想要讓剛才已經(jīng)暫存的文件在重新應(yīng)用貯藏之后也被重新暫存,我們可以在git stash apply之后加上--index選項(xiàng)

  5. 應(yīng)用了貯藏之后,堆棧上依然保留著這個(gè)貯藏的內(nèi)容,我們可以使用git stash drop <name>刪除指定貯藏內(nèi)容,例如

    $ git stash list
    stash@{0}: WIP on master: 7244031 每一個(gè)文件增加了一行數(shù)字2
    stash@{1}: WIP on master: 92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
    stash@{2}: WIP on master: 1577b44 清空所有文件
    stash@{3}: WIP on tempbranch: 91d9942 不知道怎么回事的一個(gè)提交
    stash@{4}: WIP on master: d414efe 新建了一個(gè)newile文件,并在其中輸入了一行文字
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git stash drop stash@{4}
    Dropped stash@{4} (d9d901347cfaa02cebfb55d6fe207a631c3a2ed6)
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git stash list
    stash@{0}: WIP on master: 7244031 每一個(gè)文件增加了一行數(shù)字2
    stash@{1}: WIP on master: 92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
    stash@{2}: WIP on master: 1577b44 清空所有文件
    stash@{3}: WIP on tempbranch: 91d9942 不知道怎么回事的一個(gè)提交
    
  1. 我們還可以使用git stash pop命令在應(yīng)用貯藏之后立即刪除它

貯藏的創(chuàng)意性使用

  1. git stash --keep-index不僅將已暫存的文件主藏起來(lái),還會(huì)將其保留在暫存區(qū)中。例如

    $ git stash --keep-index
    Saved working directory and index state WIP on master: 10c1009 為三個(gè)文件增加一行數(shù)字3
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git status
    On branch master
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
            modified:   a.txt
    
  1. 默認(rèn)的git stash不會(huì)將新建的文件貯藏起來(lái),只會(huì)貯藏哪些已經(jīng)跟蹤了的文件,對(duì)于還沒(méi)有跟蹤的文件是不會(huì)貯藏的。例如

    $ git status
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   a.txt
            modified:   newfile
            modified:   readme
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            b
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git stash
    Saved working directory and index state WIP on master: db19a07 為各個(gè)文件新增一行4
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git status
    On branch master
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            b
    
    nothing added to commit but untracked files present (use "git add" to track)
    
  1. 可以使用---include-untracked或者是-u選項(xiàng)讓Git的貯藏包含未跟蹤的文件。當(dāng)然這一個(gè)選項(xiàng)依然不會(huì)包含那些被忽略的文件。例如

    $ git status
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   a.txt
            modified:   newfile
            modified:   readme
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            b
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git stash -u
    warning: LF will be replaced by CRLF in b.
    The file will have its original line endings in your working directory
    Saved working directory and index state WIP on master: db19a07 為各個(gè)文件新增一行4
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git status
    On branch master
    nothing to commit, working tree clean
    
  1. 如果想要將忽略的文件也包含其中,可以使用--all或者是-a選項(xiàng)

  2. 如果指定了--patch,Git就不會(huì)貯藏所有的修改,而是進(jìn)入交互式界面讓我們選擇需要進(jìn)行貯藏的部分修改進(jìn)行貯藏

從貯藏創(chuàng)建一個(gè)分支

  1. 如果我們?cè)谫A藏了一些工作,然后繼續(xù)在貯藏的分支上工作,那之后重新應(yīng)用貯藏的時(shí)候可能就會(huì)出現(xiàn)問(wèn)題。如果應(yīng)用嘗試修改剛剛修改的文件,你會(huì)得到一個(gè)合并沖突并不得不解決它。
  2. 如果我們想要通過(guò)一個(gè)輕松的方式再次測(cè)試貯藏的改動(dòng),我們可以使用git stash branch <branchname>命令新建一個(gè)分支,并且會(huì)將貯藏的工作應(yīng)用于這一個(gè)新的分支。我們就可以在應(yīng)用成功后刪除該貯藏的內(nèi)容。
  3. 這是一個(gè)可以輕松地在一個(gè)新的分支上恢復(fù)貯藏工作并且繼續(xù)進(jìn)行工作的一個(gè)不錯(cuò)的方法。

清理工作目錄

  1. Git中可以使用git clean命令來(lái)刪除工作目錄中的一些目錄和文件。
  2. git clean命令會(huì)刪除工作目錄中未被追蹤的文件。如果我們改變了主意,我們也不一定能夠找回這些內(nèi)容。
  3. 一個(gè)更加安全的做法是git stash --all用來(lái)移除移除每一個(gè)目錄和文件并且存放在棧中。
  4. 我們可以使用git clean命令清理冗余文件和工作目錄,使用git clean -f -d命令可以移除工作目錄中所有的未被追蹤的文件以及所有空的子目錄。要使用-f選項(xiàng)要設(shè)置Git中的配置變量clean.requireForce沒(méi)有顯示為false。
  5. 如果我們只是想看看git clean命令所做的事情,我們可以使用--dry-run或者是-n選項(xiàng)來(lái)做一次演示操作
  6. 默認(rèn)情況下,git clean只會(huì)移除沒(méi)有被忽略的未跟蹤文件。如果想要移除那些被忽略的文件,需要增加一個(gè)-x選項(xiàng)
  7. 還可以使用-i選項(xiàng)進(jìn)行交互式清理操作。
  8. ==注意==: 如果我們的工作目錄中復(fù)制了別的倉(cāng)庫(kù),這時(shí)候,我們即使使用git clean -f -d也不能夠刪除這些目錄。這時(shí)候我們?nèi)绻獎(jiǎng)h除這些目錄,需要加上第二個(gè)-f選項(xiàng)。

搜索

不論倉(cāng)庫(kù)中的代碼量有多少,我們經(jīng)常需要查找一個(gè)函數(shù)是在哪里被調(diào)用和定義的,或者是我們想要了解一個(gè)方法的變更歷史。Git提供了兩個(gè)有用的工具用于快速地從其數(shù)據(jù)庫(kù)中瀏覽代碼和提交。

Git Grep

  1. Git提供了一個(gè)grep命令,可以方便地從提交歷史、工作目錄甚至是索引中查找一個(gè)字符串或者正則表達(dá)式

  2. 默認(rèn)情況下git grep命令查找的是我們的工作目錄下的文件。我們可以使用-n或者--line-number選項(xiàng)輸出匹配行的行號(hào)。例如

    $ git grep -n main
    hello.c:3:int main(void){
    multipleAB.c:3:int main(void){
    
  1. -c或者--count選項(xiàng)用于輸出概述信息。這些信息包括那些包含匹配字符串的文件以及每一個(gè)文件包含了多少匹配。例如

    $ git grep -c int
    hello.c:2
    multipleAB.c:5
    
  1. 如果我們還關(guān)心搜索字符串的上下文,那么可以使用-p或者是--show-function選項(xiàng)來(lái)顯示每一個(gè)匹配的字符串所在的方法或者函數(shù)。例如

    $ git grep --show-function int
    hello.c:int main(void){
    hello.c:        printf("Hello C\n");
    multipleAB.c:int main(void){
    multipleAB.c:   int a;
    multipleAB.c:   int b;
    multipleAB.c:   printf("輸入兩個(gè)數(shù)\n");
    multipleAB.c:   printf("%d * %d = %d\n", a, b, a * b);
    

Git日志搜索

  1. 有時(shí)候我們可能并不想知道某一項(xiàng)在哪里,我們更加關(guān)心的是這樣的字符串是什么時(shí)候引入的

  2. git log命令有許多強(qiáng)大的功能可以通過(guò)提交信息甚至是diff的內(nèi)容來(lái)找到某個(gè)特定的提交

  3. 使用-S選項(xiàng)來(lái)顯示新增和刪除某一個(gè)字符串的提交。例如

    $ git log -S a --oneline
    e8d6683 為multipleAB.c源程序添加了交互式輸入的功能
    ce7e504 新建一個(gè)multipleAB的c源代碼文件,用于計(jì)算兩個(gè)整數(shù)的乘積
    7c3bc83 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    67520cb 新建一個(gè)hello.c文件
    
  1. 如果我們想要更加精確的搜索結(jié)果,我們可以使用-G選項(xiàng)來(lái)使用正則表達(dá)式搜索。
行日志搜索
  1. 行日志搜索是另一個(gè)相當(dāng)高級(jí)并且有用的日志搜索功能。在git log后面跟上-L選項(xiàng)即可調(diào)用,它可以展示代碼中一行或者是一個(gè)函數(shù)的歷史

  2. 例如,如果我們想要查看main函數(shù)在multipleAB.c中的每一次變更,可以使用如下的命令

    $ git log -L :main:multipleAB.c
    commit e8d66837996c4857c25ebd44a8a522918c765388
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 17:22:05 2020 +0800
    
        為multipleAB.c源程序添加了交互式輸入的功能
    
    diff --git a/multipleAB.c b/multipleAB.c
    --- a/multipleAB.c
    +++ b/multipleAB.c
    @@ -3,6 +3,8 @@
     int main(void){
    -       int a=6;
    -       int b=10;
    +       int a;
    +       int b;
    +       printf("輸入兩個(gè)數(shù)\n");
    +       scanf("%d %d", &a, &b);
            printf("%d * %d = %d\n", a, b, a * b);
            return 0;
     }
    
    commit ce7e50424747351da5ea68108c673163e496c4a4
    Author: Square John <1042009398@qq.com>
    Date:   Sun May 31 15:12:37 2020 +0800
    
        新建一個(gè)multipleAB的c源代碼文件,用于計(jì)算兩個(gè)整數(shù)的乘積
    
    diff --git a/multipleAB.c b/multipleAB.c
    --- /dev/null
    +++ b/multipleAB.c
    @@ -0,0 +3,6 @@
    +int main(void){
    +       int a=6;
    +       int b=10;
    +       printf("%d * %d = %d\n", a, b, a * b);
    +       return 0;
    +}
    

重寫歷史

  1. 很多時(shí)候我們可能想要修改我們的提交歷史。這可能涉及到改變提交的順序、改變提交中的信息或者是文件、將提交壓縮或者是拆分,甚至是完全移除提交。
  2. 我們應(yīng)該注意,我們上面的這些操作都應(yīng)該是在我們將我們進(jìn)行的工作與他人進(jìn)行共享之前在本地進(jìn)行,一旦我們將倉(cāng)庫(kù)的內(nèi)容進(jìn)行了共享,就不應(yīng)該隨便重寫這些提交的歷史

修改最后一次提交

  1. 修改我們的最近一次提交可能是所有修改歷史提交操作中最常見(jiàn)的一個(gè)。

  2. 對(duì)于我們的最近的一次提交,我們往往想做兩件事:一個(gè)是簡(jiǎn)單地修改提交信息,另外一個(gè)就是通過(guò)添加、移除或者是修改文件更改實(shí)際的提交內(nèi)容。

  3. 如果只想要修改最近一次的提交信息,我們可以使用git commit --amend命令。執(zhí)行這個(gè)命令之后,就會(huì)跳轉(zhuǎn)到提交信息編輯界面供我們修改提交信息。

    • 最后一次提交信息修改前

      $ git log --oneline
      a32930d (HEAD -> master) 為hello.c新增加一行6
      db19a07 為各個(gè)文件新增一行4
      10c1009 為三個(gè)文件增加一行數(shù)字3
      7244031 每一個(gè)文件增加了一行數(shù)字2
      92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
      1577b44 清空所有文件
      d414efe 新建了一個(gè)newile文件,并在其中輸入了一行文字
      e8d6683 為multipleAB.c源程序添加了交互式輸入的功能
      df951bd 為readme新增加了一行
      345fecd 又給a.txt新增加一行
      de97888 新增一個(gè)a.txt文件
      ce7e504 新建一個(gè)multipleAB的c源代碼文件,用于計(jì)算兩個(gè)整數(shù)的乘積
      7c3bc83 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
      25dd4cc Merge branch 'newbranch'
      14e9ff1 刪除了打印hello world這一行
      35241b9 為readme文件新增了一行
      2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
      62ed47d 新增一個(gè)readme文件
      a5d2b56 添加一行'Hello C'
      b1fc8a9 將換行符作為單獨(dú)一行輸出
      67520cb 新建一個(gè)hello.c文件
      
- 最后一次提交信息修改之后

    ```bash
    $ git commit --amend
    hint: Waiting for your editor to close the file...
    [main 2020-06-13T03:07:11.693Z] update#setState idle
    [master 81fc22d] 為a.txt新增加一行6
     Date: Sat Jun 13 11:06:36 2020 +0800
     1 file changed, 2 insertions(+)
    
    helloworld@surface MINGW64 ~/Desktop/cpl (master)
    $ git log --oneline
    81fc22d (HEAD -> master) 為a.txt新增加一行6
    db19a07 為各個(gè)文件新增一行4
    10c1009 為三個(gè)文件增加一行數(shù)字3
    7244031 每一個(gè)文件增加了一行數(shù)字2
    92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
    1577b44 清空所有文件
    d414efe 新建了一個(gè)newile文件,并在其中輸入了一行文字
    e8d6683 為multipleAB.c源程序添加了交互式輸入的功能
    df951bd 為readme新增加了一行
    345fecd 又給a.txt新增加一行
    de97888 新增一個(gè)a.txt文件
    ce7e504 新建一個(gè)multipleAB的c源代碼文件,用于計(jì)算兩個(gè)整數(shù)的乘積
    7c3bc83 為hello.c添加了一段程序用于求兩個(gè)整數(shù)的相加的結(jié)果
    25dd4cc Merge branch 'newbranch'
    14e9ff1 刪除了打印hello world這一行
    35241b9 為readme文件新增了一行
    2b3775c 修改了hello.c文件中的換行符位置錯(cuò)誤
    62ed47d 新增一個(gè)readme文件
    a5d2b56 添加一行'Hello C'
    b1fc8a9 將換行符作為單獨(dú)一行輸出
    67520cb 新建一個(gè)hello.c文件
    ```
  1. 另一方面,如果我們想要修改最后一次提交的實(shí)際內(nèi)容,其流程如下

    1. 先補(bǔ)上想做的修改,

    2. 然后暫存它們,

    3. 然后使用git commit --amend命令使用新的提交代替舊的提交

    4. 例如

      • 修改前的提交

        $ git log --oneline -5
        81fc22d (HEAD -> master) 為a.txt新增加一行6
        db19a07 為各個(gè)文件新增一行4
        10c1009 為三個(gè)文件增加一行數(shù)字3
        7244031 每一個(gè)文件增加了一行數(shù)字2
        92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
        
    - 修改后的提交

        ```bash
        $ git log --oneline -5
        8210372 (HEAD -> master) 為a.txt新增加一行6以及新增了一行7
        db19a07 為各個(gè)文件新增一行4
        10c1009 為三個(gè)文件增加一行數(shù)字3
        7244031 每一個(gè)文件增加了一行數(shù)字2
        92e51d0 每一個(gè)文件中寫入了一行數(shù)字1
        ```
  1. 使用--amend選項(xiàng)的時(shí)候要注意:這樣的修改會(huì)改變提交的SHA-1校驗(yàn)和。它類似于一個(gè)小變基,所以我們?cè)谶@之前已經(jīng)將最后一次提交進(jìn)行了推送,那么我們就不應(yīng)該使用它。

  2. 如果我們的修改是瑣碎的(例如修改了一個(gè)比武或者是添加了一個(gè)忘記暫存的文件),那么這種時(shí)候我們可能不需要修改提交信息,那么我們就可以使用--no-edit選項(xiàng)跳過(guò)修改提交信息的步驟。具體命令如下

    $ git commit --amend --no-edit
    

重置揭秘

工作流程

經(jīng)典的Git工作流程是通過(guò)操縱下面這三個(gè)區(qū)域來(lái)以更加連續(xù)的狀態(tài)記錄項(xiàng)目快照的。

image-20200613174548865
  1. git add命令會(huì)將文件復(fù)制到Index
  2. git commit會(huì)取得Index中的內(nèi)容并將其保存為一個(gè)永久的快照,然后創(chuàng)建一個(gè)指向該快照的提交對(duì)象,然后更新master來(lái)指向本次提交

重置(reset)的作用

  1. git reset --soft HEAD~會(huì)同步移動(dòng)HEAD以及其所指向的指針
  2. git reset [--mixed] HEAD~在移動(dòng)HEAD以及其指向的指針之后會(huì)將HEAD所指向的分支的文件復(fù)制到Index中。值得一說(shuō)的是,這個(gè)--mixed可以忽略,默認(rèn)就是這個(gè)選項(xiàng)
  3. git reset --hard HEAD~--mixed的基礎(chǔ)上,還會(huì)將Index中的內(nèi)容復(fù)制到Working Derictory

通過(guò)路徑來(lái)重置

  1. git reset [HEAD] <filename>會(huì)將當(dāng)前HEAD所指向的分支的提交中的指定文件恢復(fù)到Index

  2. 我們還可以指定一個(gè)提交版本(使用其校驗(yàn)和或者是部分校驗(yàn)和)中的文件用于進(jìn)行恢復(fù)。例如

    $ git reset [HashCode] <filename>
    

壓縮

我們還可以使用reset命令進(jìn)行壓縮的提交。

  1. 假設(shè)有一個(gè)提交,實(shí)際上是一個(gè)未完成的工作,屬于接下來(lái)將要提交的一個(gè)中間過(guò)程,那么我們就可以使用git reset --soft HEAD^1HAD以及其所指向的分支重置到最新提交的父提交上;
  2. 然后我們?cè)俅芜\(yùn)行git commit命令,就相當(dāng)于我們丟棄了那個(gè)中間的提交,然后新創(chuàng)建了一個(gè)提交,這個(gè)提交指向那個(gè)被拋棄的中間提交的父提交。

檢出(checkout)

不帶路徑
  1. git checkout <branchname>git reset --hard <branchname>類似。不過(guò)其有兩點(diǎn)區(qū)別

    • 首先一點(diǎn)就是和reset --hard不同的是,checkout對(duì)于工作目錄是安全的,它會(huì)通過(guò)檢查以確保不會(huì)將已經(jīng)更改的文件弄丟,而reset --hard直接不檢查就覆蓋工作目錄中的內(nèi)容

    • 另外一個(gè)是checkout只會(huì)移動(dòng)HEAD,而不移動(dòng)其所指的分支

    • 如圖所示

      image-20200613182157005
帶路徑

如果checkout指定一個(gè)文件路徑,那么它就和reset一樣不會(huì)移動(dòng)HEAD,而是直接用HEAD所指向的提交中的相應(yīng)文件更新索引,還會(huì)覆蓋工作目錄中的對(duì)應(yīng)文件。這就有點(diǎn)像git reset --hard [branch] <filename>(當(dāng)然,Git并不允許這樣的操作)。因此,這對(duì)于工作目錄也是不安全的。示例

$ git checkout -- <filename>

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容