今天是Git系列課程第五課,上一課我們做了Git本地提交前的準(zhǔn)備工作,今天痞子衡要講的是Git本地提交操作。
當(dāng)我們在倉庫工作區(qū)下完成了文件增刪改操作之后,并且使用git add將文件改動記錄在暫存區(qū)之后,便可以開始將其提交到Git本地倉庫。
1.本地文件改動提交git commit
Git空間本地的改動完成之后可以直接提交,有如下三種提交命令選項(xiàng):
1.1將暫存區(qū)內(nèi)容提交git commit -m ["description"]
暫存區(qū)里目前只有app/app.c文件,我們先將其提交至倉庫。
// 將暫存區(qū)里所有改動提交到本地倉庫,提交標(biāo)題為"Initial application" jay@pc MINGW64 /d/my_project/gittest (master)$ git commit -m "Initial application"
[master 0a0c0fc] Initial application
1 file changed, 7 insertions(+)
create mode 100644 app/app.c
// 查看本地提交日志,確認(rèn)提交是否已記錄在倉庫中 jay@pc MINGW64 /d/my_project/gittest (master)$ git log
commit 0a0c0fcec8a1ef56bfc6a24e68bbf1436b2ef2cf (HEAD -> master)
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sat Mar 10 21:58:36 2018 +0800
Initial application
commit 867df08b4e13649e30926b483279dddce32750c2 (origin/master, origin/HEAD)
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sat Mar 10 20:11:04 2018 +0800
second commit
1.2追加提交git commit --amend -m ["description"]
工作區(qū)里面還有app/test.c文件處于Untracked狀態(tài),我們想將其也加到1.1的提交里合并成一個提交。
// 將Untracked狀態(tài)的test.c文件添加到暫存區(qū),用于新提交 jay@pc MINGW64 /d/my_project/gittest (master)$ git add app/test.c
// 將暫存區(qū)里新改動追加提交到本地倉庫,與上一次提交進(jìn)行合并,并修改提交標(biāo)題為"Initial application and test" jay@pc MINGW64 /d/my_project/gittest (master)$ git commit --amend -m "Initial application and test"
[master 589f65b] Initial application and test
Date: Sat Mar 10 21:58:36 2018 +0800
2 files changed, 7 insertions(+)
create mode 100644 app/app.c
create mode 100644 app/test.c
// 查看本地提交日志,確實(shí)兩次提交被合并成了一個 jay@pc MINGW64 /d/my_project/gittest (master)$ git log
commit 589f65b386dd4475bb884c40ea1441d8449fdcd1 (HEAD -> master)
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sat Mar 10 21:58:36 2018 +0800
Initial application and test
commit 867df08b4e13649e30926b483279dddce32750c2 (origin/master, origin/HEAD)
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sat Mar 10 20:11:04 2018 +0800
second commit
1.3非Untracked文件的改動全部提交git commit -a -m ["description"]
我們新增一個名叫platform.c空白文件,并將其git add到暫存區(qū);且對已提交的空白test.c文件修改恢復(fù)其一開始的內(nèi)容。此時我們工作區(qū)(test.c)和暫存區(qū)(platform.c)均存在文件改動。有沒有可能一次性將test.c和platform.c改動提交上去,答案當(dāng)然是有。
// 將platform.c改動添加到暫存區(qū) jay@pc MINGW64 /d/my_project/gittest (master)$ git add app/platform.c
// 查看Git空間當(dāng)前狀態(tài),test.c改動在工作區(qū),platform.c改動在暫存區(qū) jay@pc MINGW64 /d/my_project/gittest (master)$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: app/platform.c
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: app/test.c
// 將Git空間內(nèi)非Untracked改動之外的所有改動(無論是工作區(qū)/暫存區(qū))一次性提交到本地倉庫,此處為test.c和platform.c jay@pc MINGW64 /d/my_project/gittest (master)$ git commit -a -m "Add initial platform and update test"
[master 610feaf] Add initial platform and update test
2 files changed, 6 insertions(+)
create mode 100644 app/platform.c
// 查看Git空間當(dāng)前狀態(tài),沒有任何改動記錄,說明test.c和platform.c改動已被提交到倉庫 jay@pc MINGW64 /d/my_project/gittest (master)$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
// 查看本地提交日志,又多了一次名為"Add initial platform and update test"的新提交 jay@pc MINGW64 /d/my_project/gittest (master)$ git log
commit 610feafbf5264b66dd0515f90cce79169aebd995 (HEAD -> master)
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sun Mar 11 07:46:16 2018 +0800
Add initial platform and update test
commit 589f65b386dd4475bb884c40ea1441d8449fdcd1
Author: Jay Heng <hengjie1989@foxmail.com>
Date: Sat Mar 10 21:58:36 2018 +0800
Initial application and test
需要注意的是git commit -a雖然是-all的簡寫,但其并不是將Git空間內(nèi)所有改動全部提交,其不會提交工作區(qū)里新建的文件(Untracked狀態(tài))。
2.補(bǔ)丁包方式提交
Git是分布式版本控制系統(tǒng),一個項(xiàng)目常常由多個人一起開發(fā),有時候我們想把本地的改動交給別人去完成提交,傳統(tǒng)的做法是把你改動的所有文件全部提取出來打包發(fā)送給對方,但顯然這樣做比較繁瑣,而且你的提交描述也容易丟失。Git提供了一種很好方式解決這個需求,即生成一個patch,這個patch就是你本地的一次提交的所有信息,你只需要把這個patch發(fā)給別人就可以了。
2.1生成補(bǔ)丁包git format-patch
git format-patch命令是以本地提交為基礎(chǔ)的,讓我們先看看目前本地有多少提交:
// 圖形化方式查看本地倉庫里的歷史提交,共記錄4個提交 jay@pc MINGW64 /d/my_project/gittest (master)$ gitk
由上圖可知,倉庫里一共有4次提交,其中兩次已推送到遠(yuǎn)程,還有兩次在本地未推送:
2.1.1指定任意單個提交git format-patch -1 [commit]
讓我們試著將"Initial application and test"這個提交生成patch:
// 將SHA-1號前7位為589f65b的提交生成一個patch jay@pc MINGW64 /d/my_project/gittest (master)$ git format-patch -1 589f65b0001-Initial-application-and-test.patch
此時在gittest倉庫目錄下便可以看到生成的.patch文件,讓我們用文本編輯器打開它看一看,確實(shí)包含了這個提交的所有改動。
From 589f65b386dd4475bb884c40ea1441d8449fdcd1 Mon Sep 17 00:00:00 2001
From: Jay Heng <hengjie1989@foxmail.com>
Date: Sat, 10 Mar 2018 21:58:36 +0800
Subject: [PATCH] Initial application and test
---
app/app.c | 7 +++++++
app/test.c | 0
2 files changed, 7 insertions(+)
create mode 100644 app/app.c
create mode 100644 app/test.c
diff --git a/app/app.c b/app/app.c
new file mode 100644
index 0000000..20fe868
--- /dev/null
+++ b/app/app.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+int main(void)
+{
+ printf("hello world\n");
+ return 0;
+}
\ No newline at end of file
diff --git a/app/test.c b/app/test.c
new file mode 100644
index 0000000..e69de29
--
2.16.2.windows.1
2.1.2當(dāng)前提交之前n個提交git format-patch -n
如果一次想把本地未推送的提交全部生成patch,也可以試試-n參數(shù),-1代表生成最近的一次提交的patch,-2代表生成最近兩次提交的patch,以此類推。這個參數(shù)也可以用HEAD替換,HEAD^ 等效于-1,HEAD^^等效于-2,HEAD~n等效于-n。
// 將最近3次提交全部生成patch jay@pc MINGW64 /d/my_project/gittest (master)$ git format-patch HEAD~3
0001-second-commit.patch
0002-Initial-application-and-test.patch
0003-Add-initial-platform-and-update-test.patch
// 依然是將最近3次提交全部生成patch jay@pc MINGW64 /d/my_project/gittest (master)$ git format-patch -3
0001-second-commit.patch
0002-Initial-application-and-test.patch
0003-Add-initial-platform-and-update-test.patch
2.1.3某個提交之后的所有提交git format-patch [commit]
如果你覺得用-n參數(shù)顯得有點(diǎn)繁瑣,比如本地有很多個提交,你需要先往回?cái)?shù)一共有多少個。還有一個方法是直接指定某個提交,以某個提交為基準(zhǔn)往后的所有提交全部生成patch,比如我們以"second commit"為基準(zhǔn):
// 將SHA-1號前7位為867df08的提交之后的所有提交全部生成patch jay@pc MINGW64 /d/my_project/gittest (master)$ git format-patch 867df08
0001-Initial-application-and-test.patch
0002-Add-initial-platform-and-update-test.patch
2.2應(yīng)用補(bǔ)丁包git am
2.1.3節(jié)生成了2個補(bǔ)丁包,讓我們試著用一下這兩個補(bǔ)丁包,在用之前我們需要先把本地倉庫中這兩次提交撤銷并且也不保留在工作區(qū)(即完全刪除)。
// 將最近兩次提交在倉庫里直接刪除,不留痕跡 jay@pc MINGW64 /d/my_project/gittest (master)$ git reset --hard HEAD~2
HEAD is now at 867df08 second commit
// 查看本地提交日志,確實(shí)最近兩次提交已被刪除 jay@pc MINGW64 /d/my_project/gittest (master) $ gitk
jay@pc MINGW64 /d/my_project/gittest (master)$ git status
On branch masterYour branch is up to date with 'origin/master'.Untracked files: (use "git add <file>..." to include in what will be committed) 0001-Initial-application-and-test.patch 0002-Add-initial-platform-and-update-test.patchnothing added to commit but untracked files present (use "git add" to track)
2.2.1指定單個補(bǔ)丁包git am [patch path]
讓我們試著將0001-Initial-application-and-test.patch打入我們的倉庫。
// 將名為0001-Initial-application-and-test的patch文件打入倉庫 jay@pc MINGW64 /d/my_project/gittest (master)$ git am 0001-Initial-application-and-test.patch
Applying: Initial application and test
// 查看本地提交日志,確實(shí)patch已經(jīng)進(jìn)入倉庫 jay@pc MINGW64 /d/my_project/gittest (master)$ gitk
細(xì)心的朋友可能會注意到,同一個patch在生成和打入的時候SHA-1號是不一樣的,是的,Git會保證任何時候任何人在任何本地倉庫生成的任何提交都是唯一的。
2.2.2指定目錄下所有補(bǔ)丁包git am [patch dir/*.patch]
讓我們試著將gittest目錄下的所有patch全部打入我們的倉庫,需要注意的是由于2.2.1中已經(jīng)將編號為0001 patch打入了倉庫,所有我們需要先將這個patch文件刪除,否則在打入的時候會報(bào)錯。
// 將gittest目錄下的所有patch文件全部打入倉庫 jay@pc MINGW64 /d/my_project/gittest (master)$ git am *.patch
Applying: Add initial platform and update test
// 查看本地提交日志,確實(shí)patch已經(jīng)都進(jìn)入倉庫 jay@pc MINGW64 /d/my_project/gittest (master)$ gitk