Git 中關于一次完整的提交的命令
1、創建倉庫(git init 、git clone URL)
有兩種新建 Git 項目倉庫的方法。第一種是在本地通過初始化來創建新的 Git 倉庫。第二種是從已有的 Git 遠程倉庫中克隆出一個倉庫。
1.1、通過初始化創建新倉庫
要對現有的某個項目開始用 Git 管理,只需在該項目的根目錄下,執行以下命令:
$ git init
Git 的大部分命令都需要在 Git 倉庫的目錄下(即項目的根目錄下)運行,git init 是使用 Git 倉庫的第一個命令。初始化后,在項目的根目錄下會生成一個名為 .git 的文件夾,該目錄包含了所有 Git 需要的數據和資源。
初始化后還沒有開始跟蹤管理項目中的任何一個文件,如果當前目錄下有幾個文件想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些文件進行跟蹤并放入了暫存區,然后可以進行提交,比如下面操作:
$ git add *.c $ git add README $ git commit -m 'initial project version'
1.2、通過克隆取到遠程倉庫的鏡像
通過 git clone命令能復制出一份遠程倉庫,Git 克隆下來的項目包括項目的所有歷史版本,服務器上有的數據克隆之后本地也都會有。克隆倉庫的命令格式為 git clone URL
//比如:要克隆 Ruby 語言的 Git 代碼倉庫 Grit, $ git clone git://github.com/schacon/grit.git
默認會在執行克隆命令的目錄下生成項目文件,可以發現項目文件中包含一個 .git 的文件,用于保存下載下來的所有版本記錄,然后從中取出最新版本的文件拷貝。
如果希望在克隆的時候,自己定義項目名稱,可以在上面的命令末尾指定新的名字:
//自定義項目名稱并不會影響向遠程倉庫提交代碼,因為提交時只是提交項目里的文件 $ git clone git://github.com/schacon/grit.git mygrit
2、文件狀態
工作目錄下面的所有文件都不外乎這兩種狀態:已跟蹤、未跟蹤(untracked)。
已跟蹤的文件是指已經被納入版本控制管理的文件,目前它們的狀態可能是未更新(unmodified,查看文件狀態時默認是不顯示出來的),已修改(modified)或者已放入暫存區(staged)。未跟蹤文件(untracked)一般是新建的,它們并沒有出現在前面的版本中,也不在當前的暫存區域。初次克隆某個倉庫時,工作目錄中的所有文件都屬于已跟蹤文件,且狀態為未修改。
在編輯過某些文件之后,Git 將這些文件標為已修改(modified)。我們逐步把這些修改過的文件放到暫存區域,直到最后一次性提交所有這些暫存起來的文件,如此重復。所以使用 Git 時的文件狀態變化周期如下圖:

3、檢查當前項目中文件狀態(git status)
要確定哪些文件當前處于什么狀態,可以用 git status 命令。以下是使用 git status 命令時可能會出現的一些情況
(你也可以使用 git status -s 命令來檢查狀態,但此時是用狀態碼來表示文件狀態,狀態碼解釋參考:https://blog.csdn.net/weixin_42239374/article/details/80368448)
3.1、nothing to commit
如果在克隆倉庫之后立即執行此命令,會看到類似這樣的輸出:

這說明現在的工作目錄很干凈,所有已跟蹤文件在上次提交后都未被更改過,并且沒有出現未跟蹤的文件,即沒有新建文件。
3.2、Changes to be committed

這條狀態表示下面的文件都已存入暫存區,在提交到本地倉庫時會將這些變更提交到本地倉庫中。
newfile:新增XXX文件
deleted:刪除了XXX文件
3.4、Changes not staged for commit
見3.3的圖
這條狀態表示下面的文件都未存入暫存區。在使用commit命令進行提交操作時,若未使用 -a 參數的話(即使用 git commit -am 命令:使用了-a參數時相當于同時也執行了git add. 命令),則以下文件不會提交到本地倉庫中。
modified:修改了XXX文件
3.5、Untracked files

表示以下文件還沒有被追蹤,一般是新建的文件。Git 不會自動將新建文件納入跟蹤范圍,除非你主動使用了命令行來追蹤該文件,因而不用擔心把臨時文件什么的也歸入版本管理。
當出現這種情況時,不論是 git commit –m 還是git commit –am 命令都不能將文件提交到本地倉庫中,必須執行git add . 命令,先將文件存入暫存區中,再執行提交命令,才可以將文件提交到本地倉庫中。
4、跟蹤新文件(即放入暫存區:git add)
使用命令 git add 開始跟蹤一個新文件或者把一個經修改過的文件放入暫存區。git add后面可以直接跟文件名,也可以跟目錄,如果是目錄的話,就說明要跟蹤該目錄下的所有文件(不允許在目錄后面還有文件名,那樣會顯示在該目錄下找不到任何文件,因為它把整個當成一個目錄路徑)。git不僅能判斷出 <path> 中,修改(不包括已刪除)的文件,還能判斷出新添的文件,并把它們的信息添加到暫存區中。
$ git add filename $ git add <path> //目錄的路徑是相對于根目錄的相對路徑,比如:git add ./aaa/bbb 當然前面可以不用 ./
當我們把一個文件放入了暫存區,但是并沒有提交,后來又對它進行了修改時,這時我們查看狀態這個文件會出現在兩個狀態里
假如我們在將demo.js 文件放入暫存區后,又對其進行了修改,添加了一行注釋,查看狀態時如下圖:

同一個文件出現了兩次,一次算未暫存,一次算已暫存。實際上 Git 只不過暫存了你運行 git add 命令后的版本,如果現在提交,那么提交的是添加注釋前的版本,而非當前工作目錄中的版本。所以,但凡文件進行了修改,都應該將其放入暫存區,以免將來提交的時候版本不對。
4.1、git add的一些語法
$ git add filename $ git add <path> $ git add . // 表示將所有修改添加到暫存區(包括刪除的、新建立的文件等所有) $ git add Hello* // 表示將所有以Hello開頭的文件的修改添加到暫存區 例如:HelloWorld.txt,Hello.java $ git add -u [<path>] // 表示把<path>中所有已被跟蹤的文件中被修改過或已刪除文件的信息添加到索引庫。它不會處理untracted的文件。如果省略<path>表示當前目錄。 $ git add -A: [<path>] // 表示把path中所有已被跟蹤文件中被修改過或已刪除文件和所有未跟蹤的文件信息添加到索引庫。省略<path>表示當前目錄。
5、.gitignore 文件
一般我們總會有些文件無需納入 Git 的管理,也不希望它們總出現在未跟蹤文件列表。通常都是些自動生成的文件,比如日志文件,或者編譯過程中創建的臨時文件等。這時我們可以創建一個名為 .gitignore 的文件,列出要忽略的文件模式。要養成一開始就設置好 .gitignore 文件的習慣,以免將來誤提交這類無用的文件。
5.1、.gitignore 文件創建方法
(1)在需要創建 .gitignore 文件的項目根目錄下, 右鍵選擇Git Bash 進入命令行(2)輸入 touch .gitignore ,生成“.gitignore”文件,然后就可以進行編輯了
在window上直接創建 .gitignore 文件會出錯。
5.2、.gitignore 文件規范
.gitignore 文件的規范:
- 所有空行或者以注釋符號
#開頭的行都會被 Git 忽略,不會當做 .gitignore 文件里的內容 - 可以使用 shell 所使用的簡化了的正則表達式來匹配。
- 匹配模式最后跟反斜杠(
/)說明要忽略的是目錄。 - 要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(
!)取反。
shell 所使用的簡化了的正則表達式:星號(*)匹配零個或多個任意字符;[abc]匹配任何一個列在方括號中的字符(這個例子要么匹配一個 a,要么匹配一個 b,要么匹配一個 c);問號(?)只匹配一個任意字符;如果在方括號中使用短劃線分隔兩個字符,表示所有在這兩個字符范圍內的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的數字)。
.gitignore 文件內容實例:
# 以 # 開頭的是注釋,下面表示忽略aaa.txt文件
aaa.txt
# 忽略以 .a 結尾的文件
*.a
# 但 lib.a 除外
!lib.a
# 僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO
/TODO
# 忽略 build/ 目錄下的所有文件
build/
# 忽略根目錄下的 node_modules 文件
/node_modules
# 會忽略 doc/notes.txt 但不包括 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目錄下所有擴展名為 txt 的文件
doc/**/*.txt
6、查看文件的內容變動(git diff)
git status 命令是用來查看哪些文件發生了變動,要想查看文件具體修改了什么地方,可以用 git diff 命令。git diff 會使用文件補丁的格式顯示具體添加和刪除的行。
6.1、工作區與暫存區的比較( git diff )
git diff 命令比較的是工作區和暫存區的比較,如果該文件目前沒有在暫存區(即都提交了),那么比較的就是工作區和最新版本庫里的該文件。比如:你先把 a.js 文件放入了暫存區,然后又修改了 a.js 文件,里面添加了一行注釋,這時候比較的差別就是這行注釋;如果你把 a.js 文件已經提交了,然后再進行修改,這時候 a.js 文件并沒有在暫存區里,這時候比較的就是工作區和版本庫里的修改。
有時候運行 git diff 后什么顯示都沒有,那可能是因為所有文件都已經存入暫存區了,或者沒有修改任何文件。注意,git diff 命令并不比較任何沒有被追蹤的文件。使用 git diff --stat 只顯示摘要。

git diff 命令輸出的信息意思:
(第一行)diff --git 表示結果為 git 格式的 diff ;a/demo02.js b/demo02.js 表示 a版本的demo02.js(即變動前)和b版本的 demo02.js(即變動后)。
(第二行)index ccde7a7..9278e9c 100644 :表示兩個版本的git哈希值(index 區域的ccde7a7 對象,與工作目錄區域的9278e9c 對象進行比較),最后的六位數字是對象的模式(普通文件,644權限)。
(第三、四行)表示進行比較的兩個文件。"---"表示變動前的版本,"+++"表示變動后的版本。
其它的可以參考:http://www.ruanyifeng.com/blog/2012/08/how_to_read_diff.html 中第五個:合并格式的diff
6.2、暫存區與版本庫的比較(git diff --cached 或者 git diff --staged)
git diff 命令比較的是暫存區和最新的版本庫的文件內容,輸出信息含義可見 6.1 。
6.3、查看已緩存的與未緩存的所有改動(git diff HEAD)
git diff HEAD 顯示已緩存的與未緩存的所有改動,相當于同時執行了 git diff 和 git diff --cached 。
當執行 git diff HEAD 時,有可能出現內容太多顯示不完全,只需要不斷按 Enter 鍵讓它繼續顯示接下來的內容。到最后可能會卡在 (END) 命令行上,這時候只要按 q 鍵退出即可。( q 鍵是 GIT 中的退出鍵)
7、提交更新(git commit)
git commit 命令將在暫存區的文件提交上去。在提交之前,一定要確認還有什么修改過的或新建的文件還沒有放入暫存區,否則提交的時候不會提交那些還沒暫存起來的變化。任何修改過的文件沒有暫存起來,在提交過后該文件的修改并沒有提交上去,而且該文件還是保持已修改狀態,可以在下次提交時納入版本管理。
如果修改文件過后,但是沒有把任何文件放入暫存區,這時候提交會報錯,不會成功。但凡暫存區里有文件就能提交成功,而是只把暫存區里的文件提交上去。
7.1、git commit (不帶參數彈出文本編輯器)
直接使用 git commit 命令時,會啟動文本編輯器以便輸入本次提交的說明。(默認會啟用 shell 的環境變量 $EDITOR 所指定的軟件,一般都是 vim 或 emacs。也可以使用 git config --global core.editor 命令設定自己喜歡的編輯軟件。)
默認會顯示下面的內容:

(1)按 i 鍵,最下方顯示:插入,即可編輯。(2)編輯完后按 Esc 鍵退出編輯,可以看到此時光標在最左下方。(3)輸入 ":wq" ,退出編輯界面(不要漏了前面的 : 符號)
可以看到,默認的提交消息包含最后一次運行 git status 的輸出,不過是放在注釋行里(提交時并不會把這些當做說明提交上去),另外開頭還有一空行,供你輸入提交說明。

提交后它會告訴你,當前是在哪個分支(master)提交的,本次提交的完整 SHA-1 校驗和是什么(463dc4f),以及在本次提交中,有多少文件修訂過,多少行添改和刪改過。
有時候使用 git commit 不加選項時可能會提示:Please supply the message using either -m or -F option
這是因為系統的默認的文本編輯器 vi 有問題,我們可以為 git 換一個默認的編輯器,比如 vim。輸入下面命令:
git config --global core.editor "vim"
然后就可以使用不帶參數的 git commit 命令了。提交后如果你也不在文本編輯器中輸入版本信息而是直接提交的話,此時的提交信息就會由系統自動生成,比如是:Merge branch xxx of xxx into xxx 之類的合并提示信息。
7.2、git commit -m '這里寫該版本的說明'
git commit -m '這里寫該版本的說明' 可以直接寫版本的說明信息,不會跳轉到編輯界面,推薦使用。
7.3、git commit -am ' '(或者git commit -a -m ' ')
Git 提供了一個跳過使用暫存區域的方式即 git commit -am(或者git commit -a -m)命令,使用這兩個命令時Git 就會自動把所有已經跟蹤過的文件暫存起來一并提交,從而可以不用手寫 git add 命令。
不過該命令并不會將新建的文件也放至暫存區并提交,而是只會提交已經跟蹤過的文件。
7.4、git commit --amend(修改上次提交的版本)
使用 git commit --amend 命令可以修改你最近一次提交的版本的說明信息,并且該命令還有一個作用就是能將一些最新的修改合并至上一個版本當中。
比如說你最新一次提交的版本說明信息不合規范,你就可以使用該命令來修改說明信息。執行該命令后 git 會彈出文本編輯器并且會基于上次的提交信息來讓你進行修改
git commit --amend 命令的另一個作用就是可以讓你將本地的修改追加至最近的一次提交當中。比如說你剛提交了版本:aaa,然后你又進行了一些修改操作,然后你想把這些修改追加至剛才提交的版本:aaa 當中,而不想再重新提交一個版本,這時你就可以先執行 git add . ,然后再執行 git commit --amend 命令,git 會彈出文本編輯器來讓你再次修改版本說明信息,由此就可以將這些新修改和上次提交的版本合并為一個版本。
請注意:git commit --amend 命令不會自動幫你執行 git add 命令,你要想將本地修改合并至上一版本中,需先執行 git add 命令
git commit --amend 命令還有其他幾個參數:
git commit --amend --no-edit:無需修改版本說明信息
git commit --amend -m '新版本說明信息' :直接修改版本說明信息而不用彈出文本編輯器
8、Git 中彈出的文本編輯器
在 git 中提交一個版本,如果沒有輸入版本說明信息的話 git 就可能會彈出文本編輯器,如上面的 7.1 所示。
操作文本編輯器的命令其實是 Linux 的命令,文本編輯器有三種工作模式:命令模式、輸入模式、末行模式。

默認在命令模式:
彈出的文本編輯框默認是在命令模式下,命令模式下是不能直接編輯文本的,你輸入的字母會被當作命令執行。
進入輸入模式:
在命令模式下,輸入 i、o、a 鍵會進入輸入模式,此時彈出框下方會顯示 -- INSERT--,游標會定位在最上方,此時我們就可以進行編輯。編輯完成后我們可以按 ESC 鍵,此時會退出到命令模式。我們必須得先進入命令模式才能退出,因為我們不能直接進入末行模式。
進入末行模式:
在末行模式下,先輸入 :,然后再 wq,就可以保存文件并且退出文本編輯器了。
9、刪除文件(git rm)
如果只是簡單地從工作目錄中手動刪除文件,運行 git status 時文件會顯示在 “Changes not staged for commit” 部分。此時可以先 git add . 把文件放入暫存區,然后再提交。
我們可以使用 git rm filename 命令直接刪除文件,并且此時查看狀態該文件并不會出現在 “Changes not staged for commit” 部分(其實相當于既在工作目錄上刪除了該文件,又使用git add filename 將刪除操作放入了暫存區),最后提交的時候,該文件就不再提交至版本庫了。
9.1、強制刪除已修改過的文件(git rm -f filename)
如果文件修改過,不管是否已經放入暫存區,直接使用 git rm filename 命令時都會報錯。此時應使用強制刪除命令:git rm -f filename 如下圖所示:

9.2、僅刪除暫存區中的文件(git rm --cached filename)
如果我們想把文件從暫存區中刪除,但仍然希望保留在當前工作目錄中(如果該文件不存在暫存區中,那么也會從跟蹤清單中將其刪除,下次提交時不會將該文件提交),換句話說,僅是從跟蹤清單中刪除。
比如一些大型日志文件或者一堆 .a 編譯文件,不小心納入倉庫后,要移除跟蹤但又不想把文件從工作目錄中刪除,以便稍后在 .gitignore 文件中加上以忽略提交,這時我們用 --cached 選項即可。
rm 命令后面也可以列出文件或者目錄的名字,也可以使用glob 模式匹配。
9.3、對 git 項目中的文件改名
當你對Git 項目中的文件重命名后,git中并不會識別到這是重命名操作,而是認為你刪除了之前那個文件,又重新建立了一個新文件。
比如下面我對demo.txt 文件重命名為 demo02.txt ,查看文件狀態時:


浙公網安備 33010602011771號