天天看點

git指令梳理

一、

1、git status檢視檔案送出狀态

該分支本地代碼未送出commit

git指令梳理

如果新增檔案

git指令梳理

如果已經送出了 但還沒有push到遠端

git指令梳理

該分支本地代碼和遠端代碼一緻

git指令梳理

2、日志顯示 tip:空格向下翻頁,b向上翻頁,q退出

git log:檢視曆史送出

git指令梳理

git log --pretty=oneline:以漂亮的一行顯示,包含全部哈希索引值

git指令梳理

git log --oneline:以簡潔的一行顯示,包含簡潔哈希索引值

git指令梳理

git reflog:以簡潔的一行顯示,包含簡潔哈希索引值,同時顯示移動到某個曆史版本所需的步數

git指令梳理

3.版本控制

git reset --hard 簡潔/完整哈希索引值:回到指定哈希值所對應的版本

git reset --hard HEAD:強制工作區、暫存區、本地庫為目前HEAD指針所在的版本

git reset --hard HEAD^:後退一個版本  

  tip:一個^表示回退一個版本

git reset --hard HEAD~1:後退一個版本

  tip:波浪線~後面的數字表示後退幾個版本

4.比較差異

git diff:比較工作區和暫存區的所有檔案差異

git diff <file name>:比較工作區和暫存區的指定檔案的差異

git diff HEAD|HEAD^|HEAD~|哈希索引值 <file name>:比較工作區跟本地庫的某個版本的指定檔案的差異

5.分支操作

git branch -v:檢視所有分支

git branch -d <分支名>:删除本地分支

git branch <分支名>:建立分支

git checkout <分支名>:切換分支

git merge <被合并分支名>:合并分支

  tip:如master分支合并 hot_fix分支,那麼目前必須處于master分支上,然後執行 git merge hot_fix 指令

  tip2:合并出現沖突

    ①删除git自動标記符号,如<<<<<<< HEAD、>>>>>>>等

    ②修改到滿意後,儲存退出

    ③git add <file name>

    ④git commit -m "日志資訊",此時後面不要帶檔案名

二、本地庫跟遠端庫互動:

git clone <遠端庫位址>:克隆遠端庫

  功能:①完整的克隆遠端庫為本地庫,②為本地庫建立origin别名,③初始化本地庫

git remote -v:檢視遠端庫位址别名

git remote add <别名> <遠端庫位址>:建立遠端庫位址别名

git remote rm <别名>:删除本地中遠端庫别名

git push <别名> <分支名>:本地庫某個分支推送到遠端庫,分支必須指定

git pull <别名> <分支名>:把遠端庫的修改拉取到本地

  tip:該指令包括git fetch,git merge

git fetch <遠端庫别名> <遠端庫分支名>:抓取遠端庫的指定分支到本地,但沒有合并

git merge <遠端庫别名/遠端庫分支名>:将抓取下來的遠端的分支,跟目前所在分支進行合并

git fork:複制遠端庫

  tip:一般是外面團隊的開發人員fork本團隊項目,然後進行開發,之後外面團隊發起pull request,然後本團隊進行稽核,如無問題本團隊進行merge(合并)到團隊自己的遠端庫,整個流程就是本團隊跟外面團隊的協同開發流程,Linux的團隊開發成員即為這種工作方式。

三、什麼是tag

tag是git版本庫的一個标記,指向某個commit的指針。

tag主要用于釋出版本的管理,一個版本釋出之後,我們可以為git打上 v.1.0.1 v.1.0.2 ...這樣的标簽。

tag感覺跟branch有點相似,但是本質上和分工上是不同的:

tag 對應某次commit, 是一個點,是不可移動的。

branch 對應一系列commit,是很多點連成的一根線,有一個HEAD 指針,是可以依靠 HEAD 指針移動的。

是以,兩者的差別決定了使用方式,改動代碼用 branch ,不改動隻檢視用 tag。

tag 和 branch 的互相配合使用,有時候起到非常友善的效果,例如:已經釋出了 v1.0 v2.0 v3.0 三個版本,這個時候,我突然想不改現有代碼的前提下,在 v2.0 的基礎上加個新功能,作為 v4.0 釋出。就可以檢出 v2.0 的代碼作為一個 branch ,然後作為開發分支。

1.建立tag:

建立 tag 是基于本地分支的 commit,而且與分支的推送是兩回事,就是說分支已經推送到遠端了,但是你的 tag 并沒有,如果把 tag 推送到遠端分支上,需要另外執行 tag 的推送指令。

git tag <tagName> //建立本地tag

git push origin <tagName> //推送到遠端倉庫

若存在很多未推送的本地标簽,你想一次全部推送的話:

git push origin --tags

以上是基于本地目前分支的最後的一個commit 建立的 tag ,但是如果不想以最後一個,隻想以某一個特定的送出為tag ,也是可以的,隻要你知道commit 的id。

git log --pretty=oneline //檢視目前分支的送出曆史 裡面包含 commit id

git tag -a <tagName> <commitId>

2.檢視标簽

檢視本地某個 tag 的詳細資訊:

git show <tagName>

檢視本地所有 tag:

git tag 或者 git tag -l

檢視遠端所有 tag:

git ls-remote --tags origin

3.删除标簽

本地 tag 的删除:

git tag -d <tagName>

遠端 tag 的删除:

git push origin :<tagName>

4.檢出标簽

git checkout -b <branchName> <tagName>

因為 tag 本身指向的就是一個 commit,是以和根據commit id 檢出分支是一個道理。

但是需要特别說明的是,如果我們想要修改 tag檢出代碼分支,那麼雖然分支中的代碼改變了,但是 tag标記的 commit還是同一個,标記的代碼是不會變的,這個要格外的注意。

其它

指令git tag -a <tagname> -m "XXX..." 可以指定标簽資訊。

指令git tag -a v0.1.0 -m "release 0.1.0 version" 建立附注标簽。

指令git checkout [tagname] 切換标簽。

五、Rebase

假設你現在基于遠端分支"origin",建立一個叫"mywork"的分支。

$ git checkout -b mywork origin

git指令梳理

現在我們在這個分支做一些修改,然後生成兩個送出(commit).

$ vi file.txt

$ git commit

$ vi otherfile.txt

$ git commit

...

但是與此同時,有些人也在"origin"分支上做了一些修改并且做了送出了. 這就意味着"origin"和"mywork"這兩個分支各自"前進"了,它們之間"分叉"了。

git指令梳理

在這裡,你可以用"pull"指令把"origin"分支上的修改拉下來并且和你的修改合并;結果看起來就像一個新的"合并的送出"(merge commit):

git指令梳理

但是,如果你想讓"mywork"分支曆史看起來像沒有經過任何合并一樣,你也許可以用 git rebase:

$ git checkout mywork

$ git rebase origin

這些指令會把你的"mywork"分支裡的每個送出(commit)取消掉,并且把它們臨時 儲存為更新檔(patch)(這些更新檔放到".git/rebase"目錄中),然後把"mywork"分支更新 到最新的"origin"分支,最後把儲存的這些更新檔應用到"mywork"分支上。

git指令梳理

當'mywork'分支更新之後,它會指向這些新建立的送出(commit),而那些老的送出會被丢棄。如果運作垃圾收集指令(pruning garbage collection), 這些被丢棄的送出就會删除. (請檢視 git gc)

git指令梳理

現在我們可以看一下用合并(merge)和用rebase所産生的曆史的差別:

git指令梳理

在rebase的過程中,也許會出現沖突(conflict). 在這種情況,Git會停止rebase并會讓你去解決 沖突;在解決完沖突後,用"git-add"指令去更新這些内容的索引(index), 然後,你無需執行 git-commit,隻要執行:

$ git rebase --continue

這樣git會繼續應用(apply)餘下的更新檔。

在任何時候,你可以用--abort參數來終止rebase的行動,并且"mywork" 分支會回到rebase開始前的狀态。

$ git rebase --abort

六、restash

今天在看一個bug,之前一個分支的版本是正常的,在新的分支上上加了很多日志沒找到原因,希望回溯到之前的版本,确定下從哪個送出引入的問題,但是還不想把現在的修改送出,也不希望在Git上看到目前修改的版本(帶有大量日志和調試資訊)。是以呢,查查Git有沒有提供類似功能,就找到了git stash的指令。

綜合下網上的介紹和資料,git stash(git儲藏)可用于以下情形:

  • 發現有一個類是多餘的,想删掉它又擔心以後需要檢視它的代碼,想儲存它但又不想增加一個髒的送出。這時就可以考慮git stash。
  • 使用git的時候,我們往往使用分支(branch)解決任務切換問題,例如,我們往往會建一個自己的分支去修改和調試代碼, 如果别人或者自己發現原有的分支上有個不得不修改的bug,我們往往會把完成一半的代碼commit送出到本地倉庫,然後切換分支去修改bug,改好之後再切換回來。這樣的話往往log上會有大量不必要的記錄。其實如果我們不想送出完成一半或者不完善的代碼,但是卻不得不去修改一個緊急Bug,那麼使用git stash就可以将你目前未送出到本地(和伺服器)的代碼推入到Git的棧中,這時候你的工作區間和上一次送出的内容是完全一樣的,是以你可以放心的修Bug,等到修完Bug,送出到伺服器上後,再使用git stash apply将以前一半的工作應用回來。
  • 經常有這樣的事情發生,當你正在進行項目中某一部分的工作,裡面的東西處于一個比較雜亂的狀态,而你想轉到其他分支上進行一些工作。問題是,你不想送出進行了一半的工作,否則以後你無法回到這個工作點。解決這個問題的辦法就是git stash指令。儲藏(stash)可以擷取你工作目錄的中間狀态——也就是你修改過的被追蹤的檔案和暫存的變更——并将它儲存到一個未完結變更的堆棧中,随時可以重新應用。

git stash用法

1. stash目前修改

git stash會把所有未送出的修改(包括暫存的和非暫存的)都儲存起來,用于後續恢複目前工作目錄。

比如下面的中間狀态,通過git stash指令推送一個新的儲藏,目前的工作目錄就幹淨了。

$ git status

On branch master

Changes to be committed:

new file:   style.css

Changes not staged for commit:

modified:   index.html

$ git stash

Saved working directoryandindex state WIP onmaster: 5002d47 our new homepageHEADisnowat 5002d47 our new homepage

$ git statusOn branch masternothingtocommit, working tree clean

需要說明一點,stash是本地的,不會通過git push指令上傳到git server上。

實際應用中推薦給每個stash加一個message,用于記錄版本,使用git stash save取代git stash指令。示例如下:

$ git stash save "test-cmd-stash"Saved working directory and index state On autoswitch: test-cmd-stash

HEAD 現在位于 296e8d4 remove unnecessary postion reset in onResume function

$ git stash list

stash@{0}: On autoswitch: test-cmd-stash

2. 重新應用緩存的stash

可以通過git stash pop指令恢複之前緩存的工作目錄,輸出如下:

$ git status

On branch master

nothing to commit, working tree clean

$ git stash popOn branch masterChanges to be committed:    newfile:   style.css

Changes not staged forcommit:

   modified:   index.html

Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

這個指令将緩存堆棧中的第一個stash删除,并将對應修改應用到目前的工作目錄下。

你也可以使用git stash apply指令,将緩存堆棧中的stash多次應用到工作目錄中,但并不删除stash拷貝。指令輸出如下:

$ git stash applyOn branch master

Changes to be committed:

   new file:   style.css

Changes not staged for commit:

   modified:   index.html

3. 檢視現有stash

可以使用git stash list指令,一個典型的輸出如下:

$ git stash list

stash@{0}: WIP on master: 049d078 added the index file

stash@{1}: WIP on master: c264051 Revert "added file_size"stash@{2}: WIP on master: 21d80a5 added number to log

在使用git stash apply指令時可以通過名字指定使用哪個stash,預設使用最近的stash(即stash@{0})。

4. 移除stash

可以使用git stash drop指令,後面可以跟着stash名字。下面是一個示例:

$ git stash list

stash@{0}: WIP on master: 049d078 added the index file

stash@{1}: WIP on master: c264051 Revert "added file_size"stash@{2}: WIP on master: 21d80a5 added number to log$ git stash drop stash@{0}

Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

或者使用git stash clear指令,删除所有緩存的stash。

5. 檢視指定stash的diff

可以使用git stash show指令,後面可以跟着stash名字。示例如下:

$ git stash show

index.html | 1 +

style.css | 3 +++

2 files changed, 4 insertions(+)

在該指令後面添加-p或--patch可以檢視特定stash的全部diff,如下:

$ git stash show -p

diff --git a/style.css b/style.css

new file mode 100644

index 0000000..d92368b--- /dev/null+++ b/style.css@@ -0,0 +1,3 @@+* {+  text-decoration: blink;+}diff --git a/index.html b/index.html

index 9daeafb..ebdcbd2 100644--- a/index.html+++ b/index.html@@ -1 +1,2 @@+<link rel="stylesheet" href="style.css"/>

6. 從stash建立分支

如果你儲藏了一些工作,暫時不去理會,然後繼續在你儲藏工作的分支上工作,你在重新應用工作時可能會碰到一些問題。如果嘗試應用的變更是針對一個你那之後修改過的檔案,你會碰到一個歸并沖突并且必須去化解它。如果你想用更友善的方法來重新檢驗你儲藏的變更,你可以運作 git stash branch,這會建立一個新的分支,檢出你儲藏工作時的所處的送出,重新應用你的工作,如果成功,将會丢棄儲藏。

$ git stash branch testchanges

Switched to a new branch "testchanges"# On branch testchanges# Changes to be committed:#   (use "git reset HEAD <file>..." to unstage)##      modified:   index.html## Changes not staged for commit:#   (use "git add <file>..." to update what will be committed)##      modified:   lib/simplegit.rb#Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

這是一個很棒的捷徑來恢複儲藏的工作然後在新的分支上繼續當時的工作。

7. 暫存未跟蹤或忽略的檔案

預設情況下,git stash會緩存下列檔案:

  • 添加到暫存區的修改(staged changes)
  • Git跟蹤的但并未添加到暫存區的修改(unstaged changes)

但不會緩存一下檔案:

  • 在工作目錄中新的檔案(untracked files)
  • 被忽略的檔案(ignored files)

git stash指令提供了參數用于緩存上面兩種類型的檔案。使用-u或者--include-untracked可以stash untracked檔案。使用-a或者--all指令可以stash目前目錄下的所有修改。

至于git stash的其他指令建議參考Git manual。

8、

場景如下,你正在開發需求1時,突然線上發現了一個bug,需要立即修複。需求1的代碼因為不完善,也沒經過測試,是以你希望針對需求1所做的修改先暫時隐藏,這樣就可以使用 stash功能了。

VCS-->git -->stash

git指令梳理

這個時候針對需求1做的修改都會隐藏掉。現在假設你處理bug完畢。需要繼續開發需求,現在需要unstash

VCS-->git-->Unstash,選中你剛剛的stash,選中Pop stash。點選pop stash即可。如下圖:

但是我這裡遇到個問題,螢幕右下角有如下提示:

git指令梳理

點選View them,發現是.DS_store 檔案,這個我已經在.gitignore中聲明忽略該檔案了。是以我的localChanges中并沒有該檔案。

沒辦法,隻有先修改.gitignore,不忽略.DS_store.然後執行git status 能看到兩個檔案被修改了

git指令梳理