Git基本操作

●?git?init——初始化倉(cāng)庫(kù)

要使用Git進(jìn)行版本管理,必須先初始化倉(cāng)庫(kù)。Git是使用git init命令進(jìn)行初始化的。請(qǐng)實(shí)際建立一個(gè)目錄并初始化倉(cāng)庫(kù)。

$ mkdir gitlianxi

$ cd git-lianxi

$ git init

Initialized empty Git repository in E:/gitlianxi/.git/

如果初始化成功,執(zhí)行了 git init命令的目錄下就會(huì)生成 .git 目 錄。這個(gè) .git 目錄里存儲(chǔ)著管理當(dāng)前目錄內(nèi)容所需的倉(cāng)庫(kù)數(shù)據(jù)。 在 Git中,我們將這個(gè)目錄的內(nèi)容稱為“附屬于該倉(cāng)庫(kù)的工作樹”。 文件的編輯等操作在工作樹中進(jìn)行,然后記錄到倉(cāng)庫(kù)中,以此管理文件 的歷史快照。如果想將文件恢復(fù)到原先的狀態(tài),可以從倉(cāng)庫(kù)中調(diào)取之前 的快照,在工作樹中打開(kāi)。開(kāi)發(fā)者可以通過(guò)這種方式獲取以往的文件。

mkdir——?jiǎng)?chuàng)建文件夾(不能對(duì)文件夾里面進(jìn)行修改)

cd——進(jìn)入文件夾的路徑

● git?status——查看倉(cāng)庫(kù)的狀態(tài)?

git status命令用于顯示 Git 倉(cāng)庫(kù)的狀態(tài)。這是一個(gè)十分常用的 命令,請(qǐng)務(wù)必牢記。 工作樹和倉(cāng)庫(kù)在被操作的過(guò)程中,狀態(tài)會(huì)不斷發(fā)生變化。在Git操 作過(guò)程中時(shí)常用 git status命令查看當(dāng)前狀態(tài),可謂基本中的基本。 下面,就讓我們來(lá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分支下,還顯示了沒(méi)有可提交的內(nèi)容。所謂提交 (Commit),是指“記錄工作樹中所有文件的當(dāng)前狀態(tài)”。 尚沒(méi)有可提交的內(nèi)容,就是說(shuō)當(dāng)前我們建立的這個(gè)倉(cāng)庫(kù)中還沒(méi)有記 錄任何文件的任何狀態(tài)。這里,我們建立 README.md文件作為管理對(duì) 象,為第一次提交做前期準(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文件。類似地, 只要對(duì) Git 的工作樹或倉(cāng)庫(kù)進(jìn)行操作,git status命令的顯示結(jié)果就 會(huì)發(fā)生變化。

touch——在文件夾里面進(jìn)行創(chuàng)建

● git?add——向暫存區(qū)中添加文件

如果只是用Git倉(cāng)庫(kù)的工作樹創(chuàng)建了文件,那么該文件并不會(huì)被記 入 Git倉(cāng)庫(kù)的版本管理對(duì)象當(dāng)中。因此我們用 git status命令查看 README.md 文件時(shí),它會(huì)顯示在 Untracked files里。 要想讓文件成為 Git倉(cāng)庫(kù)的管理對(duì)象,就需要用 git add命令將其 加入暫存區(qū)(Stage 或者 Index)中。暫存區(qū)是提交之前的一個(gè)臨時(shí)區(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)}庫(kù)的歷史記錄

git commit命令可以將當(dāng)前暫存區(qū)中的文件實(shí)際保存到倉(cāng)庫(kù)的歷 史記錄中。通過(guò)這些記錄,我們就可以在工作樹中復(fù)原文件。

?記述一行提交信息

我們來(lái)實(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"稱作提交信息,是對(duì)這個(gè)提交的 概述。

?記述詳細(xì)提交信息

剛才我們只簡(jiǎn)潔地記述了一行提交信息,如果想要記述得更加詳 細(xì),請(qǐng)不加 -m,直接執(zhí)行 git commit命令。執(zhí)行后編輯器就會(huì)啟 動(dòng),并顯示如下結(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

#

在編輯器中記述提交信息的格式如下。

● 第一行:用一行文字簡(jiǎn)述提交的更改內(nèi)容

● 第二行:空行

?● 第三行以后:記述更改的原因和詳細(xì)內(nèi)容

只要按照上面的格式輸入,今后便可以通過(guò)確認(rèn)日志的命令或工具 看到這些記錄。 在以 #(井號(hào))標(biāo)為注釋的 Changes to be committed(要提 交的更改)欄中,可以查看本次提交中包含的文件。將提交信息按格式 記述完畢后,請(qǐng)保存并關(guān)閉編輯器,以#(井號(hào))標(biāo)為注釋的行不必刪 除。隨后,剛才記述的提交信息就會(huì)被提交。

中止提交

如果在編輯器啟動(dòng)后想中止提交,請(qǐng)將提交信息留空并直接關(guān)閉編 輯器,隨后提交就會(huì)被中止。

?查看提交后的狀態(tài)

執(zhí)行完 git commit命令后再來(lái)查看當(dāng)前狀態(tài)

$ git status

On branch master

nothing to commit, working tree clean

當(dāng)前工作樹處于剛剛完成提交的最新?tīng)顟B(tài),所以結(jié)果顯示沒(méi)有更改。

● git?log——查看提交日志

git log命令可以查看以往倉(cāng)庫(kù)中提交的日志。包括可以查看什么人在什么時(shí)候進(jìn)行了提交或合并,以及操作前后有怎樣的差別。關(guān)于 合并我們會(huì)在后面解說(shuō)。 我們先來(lái)看看剛才的 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……”是指向這個(gè)提交的哈希值。Git的其他命令中,在指向提 交時(shí)會(huì)用到這個(gè)哈希值。 Author欄中顯示我們給 Git設(shè)置的用戶名和郵箱地址。Date欄中顯 示提交執(zhí)行的日期和時(shí)間。再往下就是該提交的提交信息。

?只顯示提交信息的第一行

如果只想讓程序顯示第一行簡(jiǎn)述信息,可以在 git log命令后加 上 --pretty=short。這樣一來(lái)開(kāi)發(fā)人員就能夠更輕松地把握多個(gè) 提交

$ git log --pretty=short

commit 4bd9108cbe43b490eae000dd97bb3923787724fa (HEAD -> master)

Author: PhyllisWang666 <15346878235@163.com>

First commit

?只顯示指定目錄、文件的日志

只要在 git log命令后加上目錄名,便會(huì)只顯示該目錄下的日志。 如果加的是文件名,就會(huì)只顯示與該文件相關(guān)的日志。

$ git log README.md


?顯示文件的改動(dòng)

如果想查看提交所帶來(lái)的改動(dòng),可以加上 -p參數(shù),文件的前后差 別就會(huì)顯示在提交信息之后。

$ git log -p

比如,執(zhí)行下面的命令,就可以只查看 README.md文件的提交日 志以及提交前后的差別。

$ git log -p README.md

如上所述,git log命令可以利用多種參數(shù)幫助開(kāi)發(fā)者把握以往 提交的內(nèi)容。不必勉強(qiáng)自己一次記下全部參數(shù),每當(dāng)有想查看的日志就 積極去查,慢慢就能得心應(yīng)手了。

?● git?diff——查看更改前后的差別

git diff命令可以查看工作樹、暫存區(qū)、最新提交之間的差別。 單從字面上可能很難理解,各位不妨跟著筆者的解說(shuō)親手試一試。 我們?cè)趧倓偺峤坏?README.md 中寫點(diǎn)東西。

#git教程

##git基本操作

#######移動(dòng)

這里用 Markdown 語(yǔ)法寫下了一行題目。

?查看工作樹和暫存區(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基本操作

+#######移動(dòng)

\ No newline at end of file

由于我們尚未用 git add命令向暫存區(qū)添加任何東西,所以程序 只會(huì)顯示工作樹與最新提交狀態(tài)之間的差別。

這里解釋一下顯示的內(nèi)容。“+”號(hào)標(biāo)出的是新添加的行,被刪除的 行則用“-”號(hào)標(biāo)出。我們可以看到,這次只添加了一行。 用 git add命令將 README.md 文件加入暫存區(qū)。

$ git add README.md

?查看工作樹和最新提交的差別

如果現(xiàn)在執(zhí)行 git diff命令,由于工作樹和暫存區(qū)的狀態(tài)并無(wú) 差別,結(jié)果什么都不會(huì)顯示。要查看與最新提交的差別,請(qǐng)執(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基本操作

+#######移動(dòng)

\ No newline at end of file

養(yǎng)成一個(gè)好習(xí)慣:在執(zhí)行 git commit命令之前先執(zhí)行 git diff HEAD命令,查看本次提交與上次提交之間有什么差別,等 確認(rèn)完畢后再進(jìn)行提交。這里的 HEAD是指向當(dāng)前分支中最新一次提交 的指針。 由于我們剛剛確認(rèn)過(guò)兩個(gè)提交之間的差別,所以直接運(yùn)行g(shù)it commit命令。

$ git commit -m

"Add index" [master 5716572] Add index

1 file changed, 3 insertions(+)

保險(xiǎn)起見(jiàn),我們查看一下提交日志,確認(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

成功查到了第二個(gè)提交。

分支的操作

在進(jìn)行多個(gè)并行作業(yè)時(shí),我們會(huì)用到分支。在這類并行開(kāi)發(fā)的過(guò)程 中,往往同時(shí)存在多個(gè)最新代碼狀態(tài)。如圖 所示,從master分支創(chuàng) 建 feature-A分支和fix-B分支后,每個(gè)分支中都擁有自己的最新代碼。 master分支是Git默認(rèn)創(chuàng)建的分支,因此基本上所有開(kāi)發(fā)都是以這個(gè)分 支為中心進(jìn)行的。


從 master 分支創(chuàng)建 feature-A 分支和 fix-B 分支

不同分支中,可以同時(shí)進(jìn)行完全不同的作業(yè)。等該分支的作業(yè)完成 之后再與 master分支合并。比如 feature-A分支的作業(yè)結(jié)束后與 master 合并,如圖下所示。 通過(guò)靈活運(yùn)用分支,可以讓多人同時(shí)高效地進(jìn)行并行開(kāi)發(fā)。


feature-A 分支作業(yè)結(jié)束后的狀態(tài)


●?git?branch——顯示分支一覽表

git branch命令可以將分支名列表顯示,同時(shí)可以確認(rèn)當(dāng)前所在 分支。讓我們來(lái)實(shí)際運(yùn)行 git branch命令。

$ git branch

* master

可以看到master分支左側(cè)標(biāo)有“*”(星號(hào)),表示這是我們當(dāng)前所 在的分支。也就是說(shuō),我們正在 master分支下進(jìn)行開(kāi)發(fā)。結(jié)果中沒(méi)有顯 示其他分支名,表示本地倉(cāng)庫(kù)中只存在 master 一個(gè)分支。

?● git?checkout?-b——?jiǎng)?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分支。這時(shí)再 來(lái)查看分支列表,會(huì)顯示我們處于 feature-A 分支下。

$ git branch

* feature-A

master

feature-A分支左側(cè)標(biāo)有“*”,表示當(dāng)前分支為 feature-A。在這個(gè)狀 態(tài)下像正常開(kāi)發(fā)那樣修改代碼、執(zhí)行 git add命令并進(jìn)行提交的話, 代碼就會(huì)提交至feature-A分支。像這樣不斷對(duì)一個(gè)分支(例如 feature-A)進(jìn)行提交的操作,我們稱為“培育分支”。

下面來(lái)實(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)在我們?cè)賮?lái)看一看master分支有沒(méi)有受到影響。首先切換至 master 分支。

$ git checkout master Switched to branch 'master'

然后查看 README.md文件,會(huì)發(fā)現(xiàn) README.md文件仍然保持 原先的狀態(tài),并沒(méi)有被添加文字。feature-A分支的更改不會(huì)影響到 master分支,這正是在開(kāi)發(fā)中創(chuàng)建分支的優(yōu)點(diǎn)。只要?jiǎng)?chuàng)建多個(gè)分支,就可以在不互相影響的情況下同時(shí)進(jìn)行多個(gè)功能的開(kāi)發(fā)。

?●??切換回上一個(gè)分支

現(xiàn)在,我們?cè)偾袚Q回 feature-A 分支。

$ git checkout

Switched to branch 'feature-A'

像上面這樣用“-”(連字符)代替分支名,就可以切換至上一個(gè)分 支。當(dāng)然,將“-”替換成 feature-A 同樣可以切換到 feature-A 分支。

?● 特性分支?

Git 與 Subversion(SVN)等集中型版本管理系統(tǒng)不同,創(chuàng)建分支時(shí) 不需要連接中央倉(cāng)庫(kù),所以能夠相對(duì)輕松地創(chuàng)建分支。因此,當(dāng)今大部 分工作流程中都用到了特性(Topic)分支。 特性分支顧名思義,是集中實(shí)現(xiàn)單一特性(主題),除此之外不進(jìn) 行任何作業(yè)的分支。在日常開(kāi)發(fā)中,往往會(huì)創(chuàng)建數(shù)個(gè)特性分支,同時(shí)在 此之外再保留一個(gè)隨時(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è)。即便在開(kāi)發(fā)過(guò)程中發(fā)現(xiàn)了 BUG, 也需要再創(chuàng)建新的分支,在新分支中進(jìn)行修正?;谔囟ㄖ黝}的作業(yè)在特性分支中進(jìn)行,主題完成后再與 master分 支合并。只要保持這樣一個(gè)開(kāi)發(fā)流程,就能保證 master分支可以隨時(shí)供 人查看。這樣一來(lái),其他開(kāi)發(fā)者也可以放心大膽地從 master分支創(chuàng)建新 的特性分支。

?● 主干分支

主干分支是剛才我們講解的特性分支的原點(diǎn),同時(shí)也是合并的終 點(diǎn)。通常人們會(huì)用 master分支作為主干分支。主干分支中并沒(méi)有開(kāi)發(fā)到 一半的代碼,可以隨時(shí)供他人查看。 有時(shí)我們需要讓這個(gè)主干分支總是配置在正式環(huán)境中,有時(shí)又需要 用標(biāo)簽Tag 等創(chuàng)建版本信息,同時(shí)管理多個(gè)版本發(fā)布。擁有多個(gè)版本發(fā) 布時(shí),主干分支也有多個(gè)。

?● git?merge——合并分支?

接下來(lái),我們假設(shè) feature-A 已經(jīng)實(shí)現(xiàn)完畢,想要將它合并到主干分 支 master 中。首先切換到 master 分支。

$ git checkout master

Switched to branch 'master'

然后合并 feature-A 分支。為了在歷史記錄中明確記錄下本次分支合 并,我們需要?jiǎng)?chuàng)建合并提交。因此,在合并時(shí)加上 --no-ff參數(shù)。

$ git merge --no-ff feature-A

隨后編輯器會(huì)啟動(dòng),用于錄入合并提交的信息。

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ò)來(lái)的相關(guān)內(nèi)容,所 以可不必做任何更改。將編輯器中顯示的內(nèi)容保存,關(guān)閉編輯器,然后就會(huì)看到下面的結(jié)果。

Merge made by the 'recursive' strategy.

README.md | 2 ++

1 file changed,2 insertions(+)

這樣一來(lái),feature-A 分支的內(nèi)容就合并到 master 分支中了。

?● git?log?--graph——以圖表形式查看分支

用 git log --graph命令進(jìn)行查看的話,能很清楚地看到特性 分支(feature-A)提交的內(nèi)容已被合并。除此以外,特性分支的創(chuàng)建以 及合并也都清楚明了。


git log --graph

git log --graph命令可以用圖表形式輸出提交日志,非常直 觀,請(qǐng)大家務(wù)必記住。

● git?reset——回溯歷史版本

Git的另一特征便是可以靈活操作歷史版本。借助分散倉(cāng)庫(kù)的優(yōu)勢(shì), 可以在不影響其他倉(cāng)庫(kù)的前提下對(duì)歷史版本進(jìn)行操作。 在這里,為了讓各位熟悉對(duì)歷史版本的操作,我們先回溯歷史版 本,創(chuàng)建一個(gè)名為 fix-B 的特性分支。


回溯歷史,創(chuàng)建 fix-B 分支

? 回溯到創(chuàng)建 feature-A 分支前

讓我們先回溯到上一節(jié)feature-A分支創(chuàng)建之前,創(chuàng)建一個(gè)名為 fix-B 的特性分支。 要讓倉(cāng)庫(kù)的HEAD、暫存區(qū)、當(dāng)前工作樹回溯到指定狀態(tài),需要用 到 git reset --hard命令。只要提供目標(biāo)時(shí)間點(diǎn)的哈希值 ,就可以完全恢復(fù)至該時(shí)間點(diǎn)的狀態(tài)。事不宜遲,讓我們執(zhí)行下面的命令。

$ git reset --hard 4bd9108cbe43b490eae000dd97bb3923787724fa

HEAD is now at fd0cbf0 Add index

我們已經(jīng)成功回溯到特性分支(feature-A)創(chuàng)建之前的狀態(tài)。由于 所有文件都回溯到了指定哈希值對(duì)應(yīng)的時(shí)間點(diǎn)上,README.md文件的 內(nèi)容也恢復(fù)到了當(dāng)時(shí)的狀態(tài)。

哈希值在每個(gè)環(huán)境中各不相同,讀者請(qǐng)查看自身當(dāng)前環(huán)境中Add index 的哈希值, 進(jìn)行替換。

創(chuàng)建 fix-B 分支

現(xiàn)在我們來(lái)創(chuàng)建特性分支(fix-B)。

$ git checkout -b fix-B

Switched to a new branch 'fix-B'

作為這個(gè)主題的作業(yè)內(nèi)容,我們?cè)赗EADME.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)如圖所示。接下來(lái)我們的目標(biāo)是圖4.6 中所示的狀 態(tài),即主干分支合并 feature-A 分支的修改后,又合并了 fix-B 的修改


當(dāng)前 fix-B 分支的狀


fix-B 分支的下一步目標(biāo)


?推進(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)前倉(cāng)庫(kù)的操作日志。在日志中找出 回溯歷史之前的哈希值,通過(guò) git reset --hard命令恢復(fù)到回溯歷 史前的狀態(tài)。 首先執(zhí)行 git reflog 命令,查看當(dāng)前倉(cāng)庫(kù)執(zhí)行過(guò)的操作的日志。


在日志中,我們可以看到 commit、checkout、reset、merge等 Git命 令的執(zhí)行記錄。只要不進(jìn)行 Git 的 GC(Garbage Collection,垃圾回收), 就可以通過(guò)日志隨意調(diào)取近期的歷史狀態(tài),就像給時(shí)間機(jī)器指定一個(gè)時(shí) 間點(diǎn),在過(guò)去未來(lái)中自由穿梭一般。即便開(kāi)發(fā)者錯(cuò)誤執(zhí)行了Git操作, 基本也都可以利用 git reflog命令恢復(fù)到原先的狀態(tài)。


之前我們使用 git reset --hard命令回溯了歷史,這里又再次 通過(guò)它恢復(fù)到了回溯前的歷史狀態(tài)。


恢復(fù)歷史后的狀態(tài)

● 消除沖突?

現(xiàn)在只要合并fix-B分支,就可以得到我們想要的狀態(tài)。讓我們趕 快進(jìn)行合并操作。

這時(shí),系統(tǒng)告訴我們 README.md文件發(fā)生了沖突(Conflict)。系 統(tǒng)在合并 README.md 文件時(shí),feature-A分支更改的部分與本次想要合 并的 fix-B 分支更改的部分發(fā)生了沖突。 不解決沖突就無(wú)法完成合并,所以我們打開(kāi) README.md文件,解 決這個(gè)沖突。

?查看沖突部分并將其解決

用編輯器打開(kāi) README.md文件,就會(huì)發(fā)現(xiàn)其內(nèi)容變成了下面這個(gè) 樣子。

# Git教程

<<<<<<< HEAD?

- feature-A =======?

- fix-B

>>>>>>> fix-B

=======以上的部分是當(dāng)前HEAD的內(nèi)容,以下的部分是要合并 的 fix-B 分支中的內(nèi)容。我們?cè)诰庉嬈髦袑⑵涓某上胍臉幼印?/p>

# Git教程

? - feature-A? - fix-B

如上所示,本次修正讓feature-A與 fix-B的內(nèi)容并存于文件之中。 但是在實(shí)際的軟件開(kāi)發(fā)中,往往需要?jiǎng)h除其中之一,所以各位在處理沖 突時(shí),務(wù)必要仔細(xì)分析沖突部分的內(nèi)容后再行修改。

?提交解決后的結(jié)果

沖突解決后,執(zhí)行 git add命令與 git commit命令。

由于本次更改解決了沖突,所以提交信息記為 "Fix conflict"。

?● git?commit?--amend——修改提交信息

要修改上一條提交信息,可以使用 git commit --amend命令。 我們將上一條提交信息記為了 "Fix conflict",但它其實(shí)是 fix-B分 支的合并,解決合并時(shí)發(fā)生的沖突只是過(guò)程之一,這樣標(biāo)記實(shí)在不妥。 于是,我們要修改這條提交信息。

$ git commit --amend

執(zhí)行上面的命令后,編輯器就會(huì)啟動(dòng)。


編輯器中顯示的內(nèi)容如上所示,其中包含之前的提交信息。請(qǐng)將 提交信息的部分修改為 Merge branch 'fix-B',然后保存文件,關(guān)閉編 輯器。

[master 2e7db6f] Merge branch 'fix-B'

隨后會(huì)顯示上面這條結(jié)果。現(xiàn)在執(zhí)行 git log --graph命令, 可以看到提交日志中的相應(yīng)內(nèi)容也已經(jīng)被修改。


1
2


● git?rebase?-i——壓縮歷史

在合并特性分支之前,如果發(fā)現(xiàn)已提交的內(nèi)容中有些許拼寫錯(cuò)誤等, 不妨提交一個(gè)修改,然后將這個(gè)修改包含到前一個(gè)提交之中,壓縮成一 個(gè)歷史記錄。這是個(gè)會(huì)經(jīng)常用到的技巧,讓我們來(lái)實(shí)際操作體會(huì)一下。

?創(chuàng)建 feature-C 分支

首先,新建一個(gè) feature-C特性分支。

$ git checkout -b feature-C

Switched to a new branch 'feature-C'

作為 feature-C的功能實(shí)現(xiàn),我們?cè)?README.md文件中添加一行 文字,并且故意留下拼寫錯(cuò)誤,以便之后修正。

# Git教程

? - feature-A?

- fix-B?

- faeture-C

提交這部分內(nèi)容。這個(gè)小小的變更就沒(méi)必要先執(zhí)行 git add命令 再執(zhí)行 git commit命令了,我們用 git commit -am命令來(lái)一次 完成這兩步操作。

$ git commit -am "Add feature-C"

[feature-C 7a34294] Add feature-C

1 file changed, 1 insertion(+)

?修正拼寫錯(cuò)誤

現(xiàn)在來(lái)修正剛才預(yù)留的拼寫錯(cuò)誤。請(qǐng)各位自行修正 README.md文 件的內(nèi)容,修正后的差別如下所示。

然后進(jìn)行提交。

$ git commit -am "Fix typo"

[feature-C 6fba227] Fix typo

1 file changed, 1 insertion(+), 1 deletion(-)

錯(cuò)字漏字等失誤稱作typo,所以我們將提交信息記為 "Fix typo"。

實(shí)際上,我們不希望在歷史記錄中看到這類提交,因?yàn)榻∪臍v史記錄 并不需要它們。如果能在最初提交之前就發(fā)現(xiàn)并修正這些錯(cuò)誤,也就不 會(huì)出現(xiàn)這類提交了。

更改歷史?

因此,我們來(lái)更改歷史。將 "Fix typo"修正的內(nèi)容與之前一次的 提交合并,在歷史記錄中合并為一次完美的提交。為此,我們要用到 git rebase命令。

?$ git rebase -i HEAD~2?

用上述方式執(zhí)行 git rebase命令,可以選定當(dāng)前分支中包含 HEAD(最新提交)在內(nèi)的兩個(gè)最新歷史記錄為對(duì)象,并在編輯器中 打開(kā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成功。也就是以下面這兩個(gè)提交作為對(duì)象,將 "Fix typo"的內(nèi)容合并到了上一個(gè)提交 "Add feature-C"中,改寫成了一個(gè)新 的提交。

● 7a34294 Add feature-C?

● 6fba227 Fix typo

現(xiàn)在再查看提交日志時(shí)會(huì)發(fā)現(xiàn)Add feature-C的哈希值已經(jīng)不是 7a34294 了,這證明提交已經(jīng)被更改。

這樣一來(lái),F(xiàn)ix typo就從歷史中被抹去,也就相當(dāng)于 Add feature-C 中從來(lái)沒(méi)有出現(xiàn)過(guò)拼寫錯(cuò)誤。這算是一種良性的歷史改寫。

合并至 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分支。開(kāi)發(fā)進(jìn)展順利。

● git?remote?add——添加遠(yuǎn)程倉(cāng)庫(kù)?

在 GitHub上創(chuàng)建的倉(cāng)庫(kù)路徑為“git@github.com:用戶名 / git-tutorial.git”?,F(xiàn)在我們用 git remote add命令將它設(shè)置 成本地倉(cāng)庫(kù)的遠(yuǎn)程倉(cāng)庫(kù) A。

$ git remote add origin git@github.com:github-book/git-tutorial.git

按照上述格式執(zhí)行 git remote add命令之后,Git會(huì)自動(dòng)將 git@github.com:github-book/git-tutorial.git遠(yuǎn)程倉(cāng)庫(kù)的 名稱設(shè)置為 origin(標(biāo)識(shí)符)。

● git?push——推送至遠(yuǎn)程倉(cāng)庫(kù)


?推送至 master 分支

如果想將當(dāng)前分支下本地倉(cāng)庫(kù)中的內(nèi)容推送給遠(yuǎn)程倉(cāng)庫(kù),需要用到 git push命令。現(xiàn)在假定我們?cè)?master 分支下進(jìn)行操作。


1

像這樣執(zhí)行 git push命令,當(dāng)前分支的內(nèi)容就會(huì)被推送給遠(yuǎn)程倉(cāng)庫(kù) origin的master分支。-u參數(shù)可以在推送的同時(shí),將 origin倉(cāng)庫(kù)的 master分 支設(shè)置為本地倉(cāng)庫(kù)當(dāng)前分支的upstream(上游)。添加了這個(gè)參數(shù),將來(lái) 運(yùn)行 git pull命令從遠(yuǎn)程倉(cāng)庫(kù)獲取內(nèi)容時(shí),本地倉(cāng)庫(kù)的這個(gè)分支就可 以直接從 origin 的 master 分支獲取內(nèi)容,省去了另外添加參數(shù)的麻煩。 執(zhí)行該操作后,當(dāng)前本地倉(cāng)庫(kù)master分支的內(nèi)容將會(huì)被推送到 GitHub的遠(yuǎn)程倉(cāng)庫(kù)中。在 GitHub上也可以確認(rèn)遠(yuǎn)程 master分支的內(nèi)容和本地 master 分支相同。

?推送至 master 以外的分支

除了master分支之外,遠(yuǎn)程倉(cāng)庫(kù)也可以創(chuàng)建其他分支。舉個(gè)例子,我 們?cè)诒镜貍}(cāng)庫(kù)中創(chuàng)建 feature-D 分支,并將它以同名形式 push 至遠(yuǎn)程倉(cāng)庫(kù)。

$ git checkout -b feature-D Switched to a new branch 'feature-D'

我們?cè)诒镜貍}(cāng)庫(kù)中創(chuàng)建了 feature-D分支,現(xiàn)在將它push給遠(yuǎn)程倉(cāng) 庫(kù)并保持分支名稱不變。

$ 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)程倉(cāng)庫(kù)的 GitHub 頁(yè)面就可以查看到 feature-D 分支了。

● git?clone——獲取遠(yuǎn)程倉(cāng)庫(kù)

?獲取遠(yuǎn)程倉(cāng)庫(kù)

首先我們換到其他目錄下,將 GitHub上的倉(cāng)庫(kù) clone到本地。注意不要與之前操作的倉(cāng)庫(kù)在同一目錄下。


執(zhí)行 git clone命令后我們會(huì)默認(rèn)處于 master 分支下,同時(shí)系統(tǒng) 會(huì)自動(dòng)將origin設(shè)置成該遠(yuǎn)程倉(cāng)庫(kù)的標(biāo)識(shí)符。也就是說(shuō),當(dāng)前本地倉(cāng)庫(kù) 的 master分支與 GitHub端遠(yuǎn)程倉(cāng)庫(kù)(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ù)可以同時(shí)顯示本地倉(cāng)庫(kù)和遠(yuǎn)程倉(cāng)庫(kù)的分支信息。 結(jié)果中顯示了 remotes/origin/feature-D,證明我們的遠(yuǎn)程倉(cāng)庫(kù)中已經(jīng) 有了 feature-D 分支。

?獲取遠(yuǎn)程的 feature-D 分支

我們?cè)囍鴮?feature-D 分支獲取至本地倉(cāng)庫(kù)。

$ 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ù)的后面是本地倉(cāng)庫(kù)中新建分支的名稱。為了便于理解,我 們?nèi)詫⑵涿麨?feature-D,讓它與遠(yuǎn)程倉(cāng)庫(kù)的對(duì)應(yīng)分支保持同名。新建 分支名稱后面是獲取來(lái)源的分支名稱。例子中指定了origin/feature-D, 就是說(shuō)以名為 origin的倉(cāng)庫(kù)(這里指 GitHub端的倉(cāng)庫(kù))的 feature-D分 支為來(lái)源,在本地倉(cāng)庫(kù)中創(chuàng)建 feature-D 分支。

?向本地的 feature-D 分支提交更改

現(xiàn)在假定我們是另一名開(kāi)發(fā)者,要做一個(gè)新的提交。在README. md 文件中添加一行文字,查看更改.


按照之前學(xué)過(guò)的方式提交即可。

$ git commit -am "Add feature-D" [feature-D ed9721e] Add feature-D 1 file changed, 1 insertion(+)

?推送 feature-D 分支

現(xiàn)在來(lái)推送 feature-D 分支。


從遠(yuǎn)程倉(cāng)庫(kù)獲取feature-D分支,在本地倉(cāng)庫(kù)中提交更改,再將 feature-D分支推送回遠(yuǎn)程倉(cāng)庫(kù),通過(guò)這一系列操作,就可以與其他開(kāi)發(fā) 者相互合作,共同培育 feature-D 分支,實(shí)現(xiàn)某些功能。

?● git?pull——獲取最新的遠(yuǎn)程倉(cāng)庫(kù)分支

現(xiàn)在我們放下剛剛操作的目錄,回到原先的那個(gè)目錄下。這邊的本 地倉(cāng)庫(kù)中只創(chuàng)建了 feature-D分支,并沒(méi)有在 feature-D分支中進(jìn)行任何提交。然而遠(yuǎn)程倉(cāng)庫(kù)的feature-D分支中已經(jīng)有了我們剛剛推送的提交。 這時(shí)我們就可以使用 git pull命令,將本地的 feature-D分支更新到最新 狀態(tài)。當(dāng)前分支為 feature-D 分支。


GitHub端遠(yuǎn)程倉(cāng)庫(kù)中的feature-D分支是最新?tīng)顟B(tài),所以本地倉(cāng)庫(kù) 中的 feature-D 分支就得到了更新。今后只需要像平常一樣在本地進(jìn)行提 交再push給遠(yuǎn)程倉(cāng)庫(kù),就可以與其他開(kāi)發(fā)者同時(shí)在同一個(gè)分支中進(jìn)行 作業(yè),不斷給 feature-D 增加新功能。 如果兩人同時(shí)修改了同一部分的源代碼,push時(shí)就很容易發(fā)生沖 突。所以多名開(kāi)發(fā)者在同一個(gè)分支中進(jìn)行作業(yè)時(shí),為減少?zèng)_突情況的發(fā) 生,建議更頻繁地進(jìn)行 push 和 pull 操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書人閱讀 178,746評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,991評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,706評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 56,036評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 43,203評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,451評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,677評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,857評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,266評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,606評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,407評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,643評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容