●?git?init——初始化倉庫
要使用Git進(jìn)行版本管理崇堵,必須先初始化倉庫型诚。Git是使用git init命令進(jìn)行初始化的。請實(shí)際建立一個目錄并初始化倉庫鸳劳。
$ mkdir gitlianxi
$ cd git-lianxi
$ git init
Initialized empty Git repository in E:/gitlianxi/.git/
如果初始化成功狰贯,執(zhí)行了 git init命令的目錄下就會生成 .git 目 錄。這個 .git 目錄里存儲著管理當(dāng)前目錄內(nèi)容所需的倉庫數(shù)據(jù)赏廓。 在 Git中涵紊,我們將這個目錄的內(nèi)容稱為“附屬于該倉庫的工作樹”。 文件的編輯等操作在工作樹中進(jìn)行幔摸,然后記錄到倉庫中栖袋,以此管理文件 的歷史快照。如果想將文件恢復(fù)到原先的狀態(tài)抚太,可以從倉庫中調(diào)取之前 的快照,在工作樹中打開。開發(fā)者可以通過這種方式獲取以往的文件尿贫。
mkdir——創(chuàng)建文件夾(不能對文件夾里面進(jìn)行修改)
cd——進(jìn)入文件夾的路徑
● git?status——查看倉庫的狀態(tài)?
git status命令用于顯示 Git 倉庫的狀態(tài)电媳。這是一個十分常用的 命令,請務(wù)必牢記庆亡。 工作樹和倉庫在被操作的過程中匾乓,狀態(tài)會不斷發(fā)生變化。在Git操 作過程中時常用 git status命令查看當(dāng)前狀態(tài)又谋,可謂基本中的基本拼缝。 下面,就讓我們來實(shí)際查看一下當(dāng)前狀態(tài)彰亥。
$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)
結(jié)果顯示了我們當(dāng)前正處于 master分支下咧七,還顯示了沒有可提交的內(nèi)容。所謂提交 (Commit)任斋,是指“記錄工作樹中所有文件的當(dāng)前狀態(tài)”继阻。 尚沒有可提交的內(nèi)容,就是說當(dāng)前我們建立的這個倉庫中還沒有記 錄任何文件的任何狀態(tài)废酷。這里瘟檩,我們建立 README.md文件作為管理對 象,為第一次提交做前期準(zhǔn)備澈蟆。
$ git status
On branch master
No commits yet
Untracked files: (use "git add ..." to include in what will be committed) README.md nothing added to commit but untracked files present (use "git add" to track)
可以看到在 Untracked files中顯示了 README.md文件墨辛。類似地, 只要對 Git 的工作樹或倉庫進(jìn)行操作趴俘,git status命令的顯示結(jié)果就 會發(fā)生變化睹簇。
touch——在文件夾里面進(jìn)行創(chuàng)建
● git?add——向暫存區(qū)中添加文件
如果只是用Git倉庫的工作樹創(chuàng)建了文件,那么該文件并不會被記 入 Git倉庫的版本管理對象當(dāng)中哮幢。因此我們用 git status命令查看 README.md 文件時带膀,它會顯示在 Untracked files里。 要想讓文件成為 Git倉庫的管理對象橙垢,就需要用 git add命令將其 加入暫存區(qū)(Stage 或者 Index)中垛叨。暫存區(qū)是提交之前的一個臨時區(qū)域。
$ git add README.md
$ git status
On branch master
No commits yet Changes to be committed: (use "git rm --cached ..." to unstage)
new file: README.md?
將 README.md文件加入暫存區(qū)后柜某,git status命令的顯示結(jié) 果發(fā)生了變化嗽元。可以看到喂击,README.md文件顯示在Changes to be committed中了剂癌。
● git?commit——保存?zhèn)}庫的歷史記錄
git commit命令可以將當(dāng)前暫存區(qū)中的文件實(shí)際保存到倉庫的歷 史記錄中。通過這些記錄翰绊,我們就可以在工作樹中復(fù)原文件佩谷。
?記述一行提交信息
我們來實(shí)際運(yùn)行一下 git commit命令旁壮。
$ git commit -m "First commit"
[master (root-commit) 4bd9108] First commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
-m 參數(shù)后的 "First commit"稱作提交信息,是對這個提交的 概述谐檀。
?記述詳細(xì)提交信息
剛才我們只簡潔地記述了一行提交信息抡谐,如果想要記述得更加詳 細(xì),請不加 -m桐猬,直接執(zhí)行 git commit命令麦撵。執(zhí)行后編輯器就會啟 動,并顯示如下結(jié)果溃肪。
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: README.md
#
在編輯器中記述提交信息的格式如下免胃。
● 第一行:用一行文字簡述提交的更改內(nèi)容
● 第二行:空行
?● 第三行以后:記述更改的原因和詳細(xì)內(nèi)容
只要按照上面的格式輸入,今后便可以通過確認(rèn)日志的命令或工具 看到這些記錄惫撰。 在以 #(井號)標(biāo)為注釋的 Changes to be committed(要提 交的更改)欄中羔沙,可以查看本次提交中包含的文件。將提交信息按格式 記述完畢后润绎,請保存并關(guān)閉編輯器撬碟,以#(井號)標(biāo)為注釋的行不必刪 除。隨后莉撇,剛才記述的提交信息就會被提交呢蛤。
中止提交
如果在編輯器啟動后想中止提交,請將提交信息留空并直接關(guān)閉編 輯器棍郎,隨后提交就會被中止其障。
?查看提交后的狀態(tài)
執(zhí)行完 git commit命令后再來查看當(dāng)前狀態(tài)
$ git status
On branch master
nothing to commit, working tree clean
當(dāng)前工作樹處于剛剛完成提交的最新狀態(tài),所以結(jié)果顯示沒有更改涂佃。
● git?log——查看提交日志
git log命令可以查看以往倉庫中提交的日志励翼。包括可以查看什么人在什么時候進(jìn)行了提交或合并,以及操作前后有怎樣的差別辜荠。關(guān)于 合并我們會在后面解說汽抚。 我們先來看看剛才的 git commit命令是否被記錄了.
$ git log
commit 4bd9108cbe43b490eae000dd97bb3923787724fa (HEAD -> master)
Author: PhyllisWang666 <15346878235@163.com>
Date: Wed Feb 27 11:18:26 2019 +0800
First commit
如上圖所示,屏幕顯示了剛剛的提交操作伯病。commit欄旁邊顯示的 “4bd9108……”是指向這個提交的哈希值造烁。Git的其他命令中,在指向提 交時會用到這個哈希值午笛。 Author欄中顯示我們給 Git設(shè)置的用戶名和郵箱地址惭蟋。Date欄中顯 示提交執(zhí)行的日期和時間。再往下就是該提交的提交信息药磺。
?只顯示提交信息的第一行
如果只想讓程序顯示第一行簡述信息告组,可以在 git log命令后加 上 --pretty=short。這樣一來開發(fā)人員就能夠更輕松地把握多個 提交
$ git log --pretty=short
commit 4bd9108cbe43b490eae000dd97bb3923787724fa (HEAD -> master)
Author: PhyllisWang666 <15346878235@163.com>
First commit
?只顯示指定目錄癌佩、文件的日志
只要在 git log命令后加上目錄名木缝,便會只顯示該目錄下的日志便锨。 如果加的是文件名,就會只顯示與該文件相關(guān)的日志我碟。
$ git log README.md
?顯示文件的改動
如果想查看提交所帶來的改動鸿秆,可以加上 -p參數(shù),文件的前后差 別就會顯示在提交信息之后怎囚。
$ git log -p
比如,執(zhí)行下面的命令桥胞,就可以只查看 README.md文件的提交日 志以及提交前后的差別恳守。
$ git log -p README.md
如上所述,git log命令可以利用多種參數(shù)幫助開發(fā)者把握以往 提交的內(nèi)容贩虾。不必勉強(qiáng)自己一次記下全部參數(shù)催烘,每當(dāng)有想查看的日志就 積極去查,慢慢就能得心應(yīng)手了缎罢。
?● git?diff——查看更改前后的差別
git diff命令可以查看工作樹玫坛、暫存區(qū)贰盗、最新提交之間的差別。 單從字面上可能很難理解,各位不妨跟著筆者的解說親手試一試瀑罗。 我們在剛剛提交的 README.md 中寫點(diǎn)東西妨马。
#git教程
##git基本操作
#######移動
這里用 Markdown 語法寫下了一行題目盅视。
?查看工作樹和暫存區(qū)的差別
執(zhí)行 git diff命令沐兰,查看當(dāng)前工作樹與暫存區(qū)的差別寞秃。
$ git diff
diff --git a/README.md b/README.md
index e69de29..0f63f31 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,3 @@
+#git教程
+##git基本操作
+#######移動
\ No newline at end of file
由于我們尚未用 git add命令向暫存區(qū)添加任何東西,所以程序 只會顯示工作樹與最新提交狀態(tài)之間的差別识腿。
這里解釋一下顯示的內(nèi)容旨枯∶魉ⅲ“+”號標(biāo)出的是新添加的行,被刪除的 行則用“-”號標(biāo)出本冲。我們可以看到,這次只添加了一行贤旷。 用 git add命令將 README.md 文件加入暫存區(qū)畅铭。
$ git add README.md
?查看工作樹和最新提交的差別
如果現(xiàn)在執(zhí)行 git diff命令,由于工作樹和暫存區(qū)的狀態(tài)并無 差別坑资,結(jié)果什么都不會顯示。要查看與最新提交的差別,請執(zhí)行以下 命令。
$ git diff HEAD
diff --git a/README.md b/README.md
index e69de29..0f63f31 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,3 @@
+#git教程
+##git基本操作
+#######移動
\ No newline at end of file
養(yǎng)成一個好習(xí)慣:在執(zhí)行 git commit命令之前先執(zhí)行 git diff HEAD命令哺呜,查看本次提交與上次提交之間有什么差別,等 確認(rèn)完畢后再進(jìn)行提交。這里的 HEAD是指向當(dāng)前分支中最新一次提交 的指針。 由于我們剛剛確認(rèn)過兩個提交之間的差別,所以直接運(yùn)行g(shù)it commit命令。
$ git commit -m
"Add index" [master 5716572] Add index
1 file changed, 3 insertions(+)
保險起見,我們查看一下提交日志傲霸,確認(rèn)提交是否成功
$ git log commit
57165726eb158c4c0e6a32b15ccf972ba6fb087c (HEAD -> master)
Author: PhyllisWang666 <15346878235@163.com>
Date: Wed Feb 27 11:48:06 2019 +0800
Add index
commit4bd9108cbe43b490eae000dd97bb3923787724fa
Author: PhyllisWang666 <15346878235@163.com>
Date: Wed Feb 27 11:18:26 2019 +0800
First commit
成功查到了第二個提交厢蒜。
分支的操作
在進(jìn)行多個并行作業(yè)時,我們會用到分支尖坤。在這類并行開發(fā)的過程 中辖佣,往往同時存在多個最新代碼狀態(tài)而昨。如圖 所示务嫡,從master分支創(chuàng) 建 feature-A分支和fix-B分支后,每個分支中都擁有自己的最新代碼筛婉。 master分支是Git默認(rèn)創(chuàng)建的分支闹究,因此基本上所有開發(fā)都是以這個分 支為中心進(jìn)行的删豺。
不同分支中螃成,可以同時進(jìn)行完全不同的作業(yè)旦签。等該分支的作業(yè)完成 之后再與 master分支合并。比如 feature-A分支的作業(yè)結(jié)束后與 master 合并寸宏,如圖下所示宁炫。 通過靈活運(yùn)用分支,可以讓多人同時高效地進(jìn)行并行開發(fā)氮凝。
●?git?branch——顯示分支一覽表
git branch命令可以將分支名列表顯示羔巢,同時可以確認(rèn)當(dāng)前所在 分支。讓我們來實(shí)際運(yùn)行 git branch命令罩阵。
$ git branch
* master
可以看到master分支左側(cè)標(biāo)有“*”(星號)竿秆,表示這是我們當(dāng)前所 在的分支。也就是說稿壁,我們正在 master分支下進(jìn)行開發(fā)幽钢。結(jié)果中沒有顯 示其他分支名,表示本地倉庫中只存在 master 一個分支傅是。
?● git?checkout?-b——創(chuàng)建匪燕、切換分支?
如果想以當(dāng)前的master分支為基礎(chǔ)創(chuàng)建新的分支蕾羊,我們需要用到 git checkout -b命令。
?●?切換到 feature-A 分支并進(jìn)行提交
執(zhí)行下面的命令谎懦,創(chuàng)建名為 feature-A 的分支肚豺。
$ git checkout -b feature-A
Switched to a new branch 'feature-A'
實(shí)際上,連續(xù)執(zhí)行下面兩條命令也能收到同樣效果界拦。
$ git branch feature-A
$ git checkout feature-A
創(chuàng)建 feature-A分支吸申,并將當(dāng)前分支切換為 feature-A分支。這時再 來查看分支列表享甸,會顯示我們處于 feature-A 分支下截碴。
$ git branch
* feature-A
master
feature-A分支左側(cè)標(biāo)有“*”,表示當(dāng)前分支為 feature-A日丹。在這個狀 態(tài)下像正常開發(fā)那樣修改代碼、執(zhí)行 git add命令并進(jìn)行提交的話哲虾, 代碼就會提交至feature-A分支栅盲。像這樣不斷對一個分支(例如 feature-A)進(jìn)行提交的操作,我們稱為“培育分支”拟烫。
下面來實(shí)際操作一下该编。在 README.md 文件中添加一行。
# Git教程
? - feature-A
這里我們添加了 feature-A 這樣一行字母硕淑,然后進(jìn)行提交课竣。
$ git add README.md
$ git commit -m "Add feature-A"
[feature-A 8a6c8b9] Add feature-A
1 file changed, 2 insertions(+)
于是,這一行就添加到 feature-A 分支中了喜颁。
?●??切換到 master 分支
現(xiàn)在我們再來看一看master分支有沒有受到影響稠氮。首先切換至 master 分支曹阔。
$ git checkout master Switched to branch 'master'
然后查看 README.md文件半开,會發(fā)現(xiàn) README.md文件仍然保持 原先的狀態(tài),并沒有被添加文字赃份。feature-A分支的更改不會影響到 master分支寂拆,這正是在開發(fā)中創(chuàng)建分支的優(yōu)點(diǎn)奢米。只要創(chuàng)建多個分支,就可以在不互相影響的情況下同時進(jìn)行多個功能的開發(fā)纠永。
?●??切換回上一個分支
現(xiàn)在鬓长,我們再切換回 feature-A 分支。
$ git checkout
Switched to branch 'feature-A'
像上面這樣用“-”(連字符)代替分支名尝江,就可以切換至上一個分 支涉波。當(dāng)然,將“-”替換成 feature-A 同樣可以切換到 feature-A 分支炭序。
?● 特性分支?
Git 與 Subversion(SVN)等集中型版本管理系統(tǒng)不同啤覆,創(chuàng)建分支時 不需要連接中央倉庫,所以能夠相對輕松地創(chuàng)建分支惭聂。因此窗声,當(dāng)今大部 分工作流程中都用到了特性(Topic)分支。 特性分支顧名思義辜纲,是集中實(shí)現(xiàn)單一特性(主題)笨觅,除此之外不進(jìn) 行任何作業(yè)的分支。在日常開發(fā)中耕腾,往往會創(chuàng)建數(shù)個特性分支见剩,同時在 此之外再保留一個隨時可以發(fā)布軟件的穩(wěn)定分支。穩(wěn)定分支的角色通常 由 master 分支擔(dān)當(dāng)幽邓。
之前我們創(chuàng)建了feature-A分支炮温,這一分支主要實(shí)現(xiàn)feature-A,除 feature-A的實(shí)現(xiàn)之外不進(jìn)行任何作業(yè)牵舵。即便在開發(fā)過程中發(fā)現(xiàn)了 BUG柒啤, 也需要再創(chuàng)建新的分支,在新分支中進(jìn)行修正畸颅〉9基于特定主題的作業(yè)在特性分支中進(jìn)行,主題完成后再與 master分 支合并没炒。只要保持這樣一個開發(fā)流程涛癌,就能保證 master分支可以隨時供 人查看。這樣一來送火,其他開發(fā)者也可以放心大膽地從 master分支創(chuàng)建新 的特性分支拳话。
?● 主干分支
主干分支是剛才我們講解的特性分支的原點(diǎn),同時也是合并的終 點(diǎn)种吸。通常人們會用 master分支作為主干分支弃衍。主干分支中并沒有開發(fā)到 一半的代碼,可以隨時供他人查看坚俗。 有時我們需要讓這個主干分支總是配置在正式環(huán)境中镜盯,有時又需要 用標(biāo)簽Tag 等創(chuàng)建版本信息岸裙,同時管理多個版本發(fā)布。擁有多個版本發(fā) 布時速缆,主干分支也有多個降允。
?● git?merge——合并分支?
接下來,我們假設(shè) feature-A 已經(jīng)實(shí)現(xiàn)完畢艺糜,想要將它合并到主干分 支 master 中剧董。首先切換到 master 分支。
$ git checkout master
Switched to branch 'master'
然后合并 feature-A 分支破停。為了在歷史記錄中明確記錄下本次分支合 并送滞,我們需要創(chuàng)建合并提交。因此辱挥,在合并時加上 --no-ff參數(shù)犁嗅。
$ git merge --no-ff feature-A
隨后編輯器會啟動,用于錄入合并提交的信息晤碘。
Merge branch 'feature-A'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
默認(rèn)信息中已經(jīng)包含了是從 feature-A 分支合并過來的相關(guān)內(nèi)容褂微,所 以可不必做任何更改。將編輯器中顯示的內(nèi)容保存园爷,關(guān)閉編輯器宠蚂,然后就會看到下面的結(jié)果。
Merge made by the 'recursive' strategy.
README.md | 2 ++
1 file changed,2 insertions(+)
這樣一來童社,feature-A 分支的內(nèi)容就合并到 master 分支中了求厕。
?● git?log?--graph——以圖表形式查看分支
用 git log --graph命令進(jìn)行查看的話,能很清楚地看到特性 分支(feature-A)提交的內(nèi)容已被合并扰楼。除此以外呀癣,特性分支的創(chuàng)建以 及合并也都清楚明了。
git log --graph命令可以用圖表形式輸出提交日志弦赖,非常直 觀项栏,請大家務(wù)必記住。
● git?reset——回溯歷史版本
Git的另一特征便是可以靈活操作歷史版本蹬竖。借助分散倉庫的優(yōu)勢沼沈, 可以在不影響其他倉庫的前提下對歷史版本進(jìn)行操作。 在這里币厕,為了讓各位熟悉對歷史版本的操作列另,我們先回溯歷史版 本,創(chuàng)建一個名為 fix-B 的特性分支旦装。
? 回溯到創(chuàng)建 feature-A 分支前
讓我們先回溯到上一節(jié)feature-A分支創(chuàng)建之前,創(chuàng)建一個名為 fix-B 的特性分支同辣。 要讓倉庫的HEAD拷姿、暫存區(qū)、當(dāng)前工作樹回溯到指定狀態(tài)旱函,需要用 到 git reset --hard命令响巢。只要提供目標(biāo)時間點(diǎn)的哈希值 ,就可以完全恢復(fù)至該時間點(diǎn)的狀態(tài)棒妨。事不宜遲踪古,讓我們執(zhí)行下面的命令。
$ git reset --hard 4bd9108cbe43b490eae000dd97bb3923787724fa
HEAD is now at fd0cbf0 Add index
我們已經(jīng)成功回溯到特性分支(feature-A)創(chuàng)建之前的狀態(tài)券腔。由于 所有文件都回溯到了指定哈希值對應(yīng)的時間點(diǎn)上伏穆,README.md文件的 內(nèi)容也恢復(fù)到了當(dāng)時的狀態(tài)。
哈希值在每個環(huán)境中各不相同纷纫,讀者請查看自身當(dāng)前環(huán)境中Add index 的哈希值枕扫, 進(jìn)行替換。
創(chuàng)建 fix-B 分支
現(xiàn)在我們來創(chuàng)建特性分支(fix-B)辱魁。
$ git checkout -b fix-B
Switched to a new branch 'fix-B'
作為這個主題的作業(yè)內(nèi)容烟瞧,我們在README.md文件中添加一行 文字。
# Git教程
? - fix-B
然后直接提交 README.md 文件染簇。
$ git add README.md
$ git commit -m "Fix B"
[fix-B 4096d9e] Fix B
1 file changed, 2 insertions(+)
現(xiàn)在的狀態(tài)如圖所示参滴。接下來我們的目標(biāo)是圖4.6 中所示的狀 態(tài),即主干分支合并 feature-A 分支的修改后锻弓,又合并了 fix-B 的修改
?推進(jìn)至 feature-A 分支合并后的狀態(tài)
首先恢復(fù)到 feature-A 分支合并后的狀態(tài)砾赔。不妨稱這一操作為“推進(jìn) 歷史”。 git log命令只能查看以當(dāng)前狀態(tài)為終點(diǎn)的歷史日志青灼。所以這里 要使用 git reflog命令暴心,查看當(dāng)前倉庫的操作日志。在日志中找出 回溯歷史之前的哈希值杂拨,通過 git reset --hard命令恢復(fù)到回溯歷 史前的狀態(tài)酷勺。 首先執(zhí)行 git reflog 命令,查看當(dāng)前倉庫執(zhí)行過的操作的日志扳躬。
在日志中脆诉,我們可以看到 commit、checkout贷币、reset击胜、merge等 Git命 令的執(zhí)行記錄。只要不進(jìn)行 Git 的 GC(Garbage Collection役纹,垃圾回收)偶摔, 就可以通過日志隨意調(diào)取近期的歷史狀態(tài),就像給時間機(jī)器指定一個時 間點(diǎn)促脉,在過去未來中自由穿梭一般辰斋。即便開發(fā)者錯誤執(zhí)行了Git操作策州, 基本也都可以利用 git reflog命令恢復(fù)到原先的狀態(tài)。
之前我們使用 git reset --hard命令回溯了歷史宫仗,這里又再次 通過它恢復(fù)到了回溯前的歷史狀態(tài)够挂。
● 消除沖突?
現(xiàn)在只要合并fix-B分支,就可以得到我們想要的狀態(tài)藕夫。讓我們趕 快進(jìn)行合并操作孽糖。
這時,系統(tǒng)告訴我們 README.md文件發(fā)生了沖突(Conflict)毅贮。系 統(tǒng)在合并 README.md 文件時办悟,feature-A分支更改的部分與本次想要合 并的 fix-B 分支更改的部分發(fā)生了沖突。 不解決沖突就無法完成合并滩褥,所以我們打開 README.md文件病蛉,解 決這個沖突。
?查看沖突部分并將其解決
用編輯器打開 README.md文件瑰煎,就會發(fā)現(xiàn)其內(nèi)容變成了下面這個 樣子铡恕。
# Git教程
<<<<<<< HEAD?
- feature-A =======?
- fix-B
>>>>>>> fix-B
=======以上的部分是當(dāng)前HEAD的內(nèi)容,以下的部分是要合并 的 fix-B 分支中的內(nèi)容丢间。我們在編輯器中將其改成想要的樣子探熔。
# Git教程
? - feature-A? - fix-B
如上所示,本次修正讓feature-A與 fix-B的內(nèi)容并存于文件之中烘挫。 但是在實(shí)際的軟件開發(fā)中诀艰,往往需要刪除其中之一,所以各位在處理沖 突時饮六,務(wù)必要仔細(xì)分析沖突部分的內(nèi)容后再行修改其垄。
?提交解決后的結(jié)果
沖突解決后,執(zhí)行 git add命令與 git commit命令卤橄。
由于本次更改解決了沖突绿满,所以提交信息記為 "Fix conflict"。
?● git?commit?--amend——修改提交信息
要修改上一條提交信息窟扑,可以使用 git commit --amend命令喇颁。 我們將上一條提交信息記為了 "Fix conflict",但它其實(shí)是 fix-B分 支的合并嚎货,解決合并時發(fā)生的沖突只是過程之一橘霎,這樣標(biāo)記實(shí)在不妥。 于是殖属,我們要修改這條提交信息姐叁。
$ git commit --amend
執(zhí)行上面的命令后,編輯器就會啟動。
編輯器中顯示的內(nèi)容如上所示外潜,其中包含之前的提交信息原环。請將 提交信息的部分修改為 Merge branch 'fix-B',然后保存文件处窥,關(guān)閉編 輯器嘱吗。
[master 2e7db6f] Merge branch 'fix-B'
隨后會顯示上面這條結(jié)果。現(xiàn)在執(zhí)行 git log --graph命令碧库, 可以看到提交日志中的相應(yīng)內(nèi)容也已經(jīng)被修改。
● git?rebase?-i——壓縮歷史
在合并特性分支之前巧勤,如果發(fā)現(xiàn)已提交的內(nèi)容中有些許拼寫錯誤等嵌灰, 不妨提交一個修改,然后將這個修改包含到前一個提交之中颅悉,壓縮成一 個歷史記錄沽瞭。這是個會經(jīng)常用到的技巧,讓我們來實(shí)際操作體會一下剩瓶。
?創(chuàng)建 feature-C 分支
首先驹溃,新建一個 feature-C特性分支。
$ git checkout -b feature-C
Switched to a new branch 'feature-C'
作為 feature-C的功能實(shí)現(xiàn)延曙,我們在 README.md文件中添加一行 文字豌鹤,并且故意留下拼寫錯誤,以便之后修正枝缔。
# Git教程
? - feature-A?
- fix-B?
- faeture-C
提交這部分內(nèi)容布疙。這個小小的變更就沒必要先執(zhí)行 git add命令 再執(zhí)行 git commit命令了,我們用 git commit -am命令來一次 完成這兩步操作愿卸。
$ git commit -am "Add feature-C"
[feature-C 7a34294] Add feature-C
1 file changed, 1 insertion(+)
?修正拼寫錯誤
現(xiàn)在來修正剛才預(yù)留的拼寫錯誤灵临。請各位自行修正 README.md文 件的內(nèi)容,修正后的差別如下所示趴荸。
然后進(jìn)行提交儒溉。
$ git commit -am "Fix typo"
[feature-C 6fba227] Fix typo
1 file changed, 1 insertion(+), 1 deletion(-)
錯字漏字等失誤稱作typo,所以我們將提交信息記為 "Fix typo"发钝。
實(shí)際上顿涣,我們不希望在歷史記錄中看到這類提交,因?yàn)榻∪臍v史記錄 并不需要它們酝豪。如果能在最初提交之前就發(fā)現(xiàn)并修正這些錯誤园骆,也就不 會出現(xiàn)這類提交了。
更改歷史?
因此寓调,我們來更改歷史锌唾。將 "Fix typo"修正的內(nèi)容與之前一次的 提交合并,在歷史記錄中合并為一次完美的提交。為此晌涕,我們要用到 git rebase命令滋捶。
?$ git rebase -i HEAD~2?
用上述方式執(zhí)行 git rebase命令,可以選定當(dāng)前分支中包含 HEAD(最新提交)在內(nèi)的兩個最新歷史記錄為對象余黎,并在編輯器中 打開重窟。
我們將 6fba227 的Fix typo的歷史記錄壓縮到 7a34294 的Add feature-C 里。按照下圖所示惧财,將 6fba227 左側(cè)的 pick 部分刪除巡扇,改寫為 fixup。?
pick 7a34294 Add feature-C?
fixup 6fba227 Fix typo??
保存編輯器里的內(nèi)容垮衷,關(guān)閉編輯器厅翔。
[detached HEAD 51440c5] Add feature-C
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/feature-C.
系統(tǒng)顯示 rebase成功。也就是以下面這兩個提交作為對象搀突,將 "Fix typo"的內(nèi)容合并到了上一個提交 "Add feature-C"中刀闷,改寫成了一個新 的提交。
● 7a34294 Add feature-C?
● 6fba227 Fix typo
現(xiàn)在再查看提交日志時會發(fā)現(xiàn)Add feature-C的哈希值已經(jīng)不是 7a34294 了仰迁,這證明提交已經(jīng)被更改甸昏。
這樣一來,F(xiàn)ix typo就從歷史中被抹去徐许,也就相當(dāng)于 Add feature-C 中從來沒有出現(xiàn)過拼寫錯誤施蜜。這算是一種良性的歷史改寫。
合并至 master 分支
feature-C分支的使命告一段落雌隅,我們將它與 master 分支合并花墩。
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff feature-C
Merge made by the 'recursive' strategy.
README.md| 1 +
1 file changed, 1 insertion(+)
master 分支整合了 feature-C分支。開發(fā)進(jìn)展順利澄步。
● git?remote?add——添加遠(yuǎn)程倉庫?
在 GitHub上創(chuàng)建的倉庫路徑為“git@github.com:用戶名 / git-tutorial.git””ⅲ現(xiàn)在我們用 git remote add命令將它設(shè)置 成本地倉庫的遠(yuǎn)程倉庫 A。
$ git remote add origin git@github.com:github-book/git-tutorial.git
按照上述格式執(zhí)行 git remote add命令之后村缸,Git會自動將 git@github.com:github-book/git-tutorial.git遠(yuǎn)程倉庫的 名稱設(shè)置為 origin(標(biāo)識符)祠肥。
● git?push——推送至遠(yuǎn)程倉庫
?推送至 master 分支
如果想將當(dāng)前分支下本地倉庫中的內(nèi)容推送給遠(yuǎn)程倉庫,需要用到 git push命令√菝螅現(xiàn)在假定我們在 master 分支下進(jìn)行操作仇箱。
像這樣執(zhí)行 git push命令,當(dāng)前分支的內(nèi)容就會被推送給遠(yuǎn)程倉庫 origin的master分支东羹。-u參數(shù)可以在推送的同時剂桥,將 origin倉庫的 master分 支設(shè)置為本地倉庫當(dāng)前分支的upstream(上游)。添加了這個參數(shù)属提,將來 運(yùn)行 git pull命令從遠(yuǎn)程倉庫獲取內(nèi)容時权逗,本地倉庫的這個分支就可 以直接從 origin 的 master 分支獲取內(nèi)容美尸,省去了另外添加參數(shù)的麻煩。 執(zhí)行該操作后斟薇,當(dāng)前本地倉庫master分支的內(nèi)容將會被推送到 GitHub的遠(yuǎn)程倉庫中师坎。在 GitHub上也可以確認(rèn)遠(yuǎn)程 master分支的內(nèi)容和本地 master 分支相同。
?推送至 master 以外的分支
除了master分支之外堪滨,遠(yuǎn)程倉庫也可以創(chuàng)建其他分支胯陋。舉個例子,我 們在本地倉庫中創(chuàng)建 feature-D 分支袱箱,并將它以同名形式 push 至遠(yuǎn)程倉庫遏乔。
$ git checkout -b feature-D Switched to a new branch 'feature-D'
我們在本地倉庫中創(chuàng)建了 feature-D分支,現(xiàn)在將它push給遠(yuǎn)程倉 庫并保持分支名稱不變发笔。
$ git push -u origin feature-D
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:github-book/git-tutorial.git
* [new branch]? ? ? feature-D -> feature-D
Branch feature-D set up to track remote branch feature-D from origin.
現(xiàn)在盟萨,在遠(yuǎn)程倉庫的 GitHub 頁面就可以查看到 feature-D 分支了。
● git?clone——獲取遠(yuǎn)程倉庫
?獲取遠(yuǎn)程倉庫
首先我們換到其他目錄下筐咧,將 GitHub上的倉庫 clone到本地鸯旁。注意不要與之前操作的倉庫在同一目錄下噪矛。
執(zhí)行 git clone命令后我們會默認(rèn)處于 master 分支下量蕊,同時系統(tǒng) 會自動將origin設(shè)置成該遠(yuǎn)程倉庫的標(biāo)識符。也就是說艇挨,當(dāng)前本地倉庫 的 master分支與 GitHub端遠(yuǎn)程倉庫(origin)的 master分支在內(nèi)容上是 完全相同的残炮。
$ git branch -a
* master?
remotes/origin/HEAD -> origin/master?
remotes/origin/feature-D?
remotes/origin/master
我們用 git branch -a命令查看當(dāng)前分支的相關(guān)信息。添加 -a 參數(shù)可以同時顯示本地倉庫和遠(yuǎn)程倉庫的分支信息缩滨。 結(jié)果中顯示了 remotes/origin/feature-D势就,證明我們的遠(yuǎn)程倉庫中已經(jīng) 有了 feature-D 分支。
?獲取遠(yuǎn)程的 feature-D 分支
我們試著將 feature-D 分支獲取至本地倉庫脉漏。
$ git checkout -b feature-D origin/feature-D
Branch feature-D set up to track remote branch feature-D from origin.
Switched to a new branch 'feature-D'
-b參數(shù)的后面是本地倉庫中新建分支的名稱苞冯。為了便于理解,我 們?nèi)詫⑵涿麨?feature-D侧巨,讓它與遠(yuǎn)程倉庫的對應(yīng)分支保持同名舅锄。新建 分支名稱后面是獲取來源的分支名稱。例子中指定了origin/feature-D司忱, 就是說以名為 origin的倉庫(這里指 GitHub端的倉庫)的 feature-D分 支為來源皇忿,在本地倉庫中創(chuàng)建 feature-D 分支。
?向本地的 feature-D 分支提交更改
現(xiàn)在假定我們是另一名開發(fā)者坦仍,要做一個新的提交鳍烁。在README. md 文件中添加一行文字,查看更改.
按照之前學(xué)過的方式提交即可繁扎。
$ git commit -am "Add feature-D" [feature-D ed9721e] Add feature-D 1 file changed, 1 insertion(+)
?推送 feature-D 分支
現(xiàn)在來推送 feature-D 分支幔荒。
從遠(yuǎn)程倉庫獲取feature-D分支,在本地倉庫中提交更改,再將 feature-D分支推送回遠(yuǎn)程倉庫铺峭,通過這一系列操作墓怀,就可以與其他開發(fā) 者相互合作,共同培育 feature-D 分支卫键,實(shí)現(xiàn)某些功能傀履。
?● git?pull——獲取最新的遠(yuǎn)程倉庫分支
現(xiàn)在我們放下剛剛操作的目錄,回到原先的那個目錄下莉炉。這邊的本 地倉庫中只創(chuàng)建了 feature-D分支钓账,并沒有在 feature-D分支中進(jìn)行任何提交。然而遠(yuǎn)程倉庫的feature-D分支中已經(jīng)有了我們剛剛推送的提交絮宁。 這時我們就可以使用 git pull命令梆暮,將本地的 feature-D分支更新到最新 狀態(tài)。當(dāng)前分支為 feature-D 分支绍昂。
GitHub端遠(yuǎn)程倉庫中的feature-D分支是最新狀態(tài)啦粹,所以本地倉庫 中的 feature-D 分支就得到了更新。今后只需要像平常一樣在本地進(jìn)行提 交再push給遠(yuǎn)程倉庫窘游,就可以與其他開發(fā)者同時在同一個分支中進(jìn)行 作業(yè)唠椭,不斷給 feature-D 增加新功能。 如果兩人同時修改了同一部分的源代碼忍饰,push時就很容易發(fā)生沖 突贪嫂。所以多名開發(fā)者在同一個分支中進(jìn)行作業(yè)時,為減少沖突情況的發(fā) 生艾蓝,建議更頻繁地進(jìn)行 push 和 pull 操作力崇。