Git命令備忘錄

Git學習筆記

1.Git簡介

1.1 Git產生歷史

很多人都知道,Linus在1991年創(chuàng)建了開源的Linux,從此,Linux系統(tǒng)不斷發(fā)展,已經(jīng)成為最大的服務器系統(tǒng)軟件了。

Linus雖然創(chuàng)建了Linux,但Linux的壯大是靠全世界熱心的志愿者參與的,這么多人在世界各地為Linux編寫代碼,那Linux的代碼是如何管理的呢?

事實是,在2002年以前,世界各地的志愿者把源代碼文件通過diff的方式發(fā)給Linus,然后由Linus本人通過手工方式合并代碼!

你也許會想,為什么Linus不把Linux代碼放到版本控制系統(tǒng)里呢?不是有CVS、SVN這些免費的版本控制系統(tǒng)嗎?因為Linus堅定地反對CVS和SVN,這些集中式的版本控制系統(tǒng)不但速度慢,而且必須聯(lián)網(wǎng)才能使用。有一些商用的版本控制系統(tǒng),雖然比CVS、SVN好用,但那是付費的,和Linux的開源精神不符。

不過,到了2002年,Linux系統(tǒng)已經(jīng)發(fā)展了十年了,代碼庫之大讓Linus很難繼續(xù)通過手工方式管理了,社區(qū)的弟兄們也對這種方式表達了強烈不滿,于是Linus選擇了一個商業(yè)的版本控制系統(tǒng)BitKeeper,BitKeeper的東家BitMover公司出于人道主義精神,授權Linux社區(qū)免費使用這個版本控制系統(tǒng)。

安定團結的大好局面在2005年就被打破了,原因是Linux社區(qū)牛人聚集,不免沾染了一些梁山好漢的江湖習氣。開發(fā)Samba的Andrew試圖破解BitKeeper的協(xié)議(這么干的其實也不只他一個),被BitMover公司發(fā)現(xiàn)了(監(jiān)控工作做得不錯?。?,于是BitMover公司怒了,要收回Linux社區(qū)的免費使用權。

Linus可以向BitMover公司道個歉,保證以后嚴格管教弟兄們,嗯,這是不可能的。實際情況是這樣的:

Linus花了兩周時間自己用C寫了一個分布式版本控制系統(tǒng),這就是Git!一個月之內,Linux系統(tǒng)的源碼已經(jīng)由Git管理了!牛是怎么定義的呢?大家可以體會一下。

Git迅速成為最流行的分布式版本控制系統(tǒng),尤其是2008年,GitHub網(wǎng)站上線了,它為開源項目免費提供Git存儲,無數(shù)開源項目開始遷移至GitHub,包括jQuery,PHP,Ruby等等。

歷史就是這么偶然,如果不是當年BitMover公司威脅Linux社區(qū),可能現(xiàn)在我們就沒有免費而超級好用的Git了。

1.2 Git特點

A.版本控制
可以解決多人同時開發(fā)的代碼問題,也可以解決找回歷史代碼的問題

B.分布式
Git是分布式版本控制系統(tǒng),同一個Git倉庫,可以分布到不同的機器上。首先找一臺電腦充當服務器,每天24小時開機,其他每個人都從這個服務器倉庫克隆一份代碼到自己的電腦上,并且各自把各自的提交推送到服務器倉庫里,也從服務器倉庫中拉取別人的提交,可以自己搭建這臺服務器,可以使用GitHub、碼云等。

1.3 Git相關網(wǎng)站

2.Git安裝和配置

在安裝之前,都可以在終端里,查看當前是否已安裝和安裝的版本:

# 查看git命令是否可用
$ git
# 查看git版本
$ git --version

2.1 Ubuntu

安裝命令

$ sudo apt-get install git

2.2 Mac

一:一般情況下,Mac系統(tǒng)都自帶了Git,特別是安裝了Xcode的情況下,Command Line Tools命令行工具里,是包含Git組件的。

二:一是安裝homebrew,然后通過homebrew安裝Git,具體方法請參考homebrew的文檔:

http://brew.sh/

2.3 Windows

去上節(jié)Git官網(wǎng)下載Git客戶端即可。

2.4 Git配置

安裝完成后,還需要最后一步設置,在命令行輸入:

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

注意git config命令的--global參數(shù),用了這個參數(shù),表示你這臺機器上所有的Git倉庫都會使用這個配置,當然也可以對某個倉庫指定不同的用戶名和Email地址

3.創(chuàng)建版本庫

3.1 創(chuàng)建版本庫

什么是版本庫呢?版本庫又名倉庫,英文名repository,你可以簡單理解成一個目錄,這個目錄里面的所有文件都可以被Git管理起來,每個文件的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”

所以,創(chuàng)建一個版本庫非常簡單,首先,選擇一個合適的地方,創(chuàng)建一個空目錄:

$ mkdir gitTest
$ cd gitTest
$ pwd
/Users/houwan/Desktop/gitTest

最好目錄不要有中文,防止出現(xiàn)各種神奇問題

第二步,通過git init命令把這個目錄變成Git可以管理的倉庫:

$ git init
Initialized empty Git repository in /Users/houwan/Desktop/gitTest/.git/
  • 此時倉庫建好了,而且告訴你是一個空的倉庫(empty Git repository)
  • .git文件夾是Git來跟蹤管理版本庫的,默認隱藏,使用ls -al可以看到
  • 不一定必須在空目錄下創(chuàng)建Git倉庫,選擇一個已經(jīng)有東西的目錄也是可以的

3.2 添加文件到版本庫

首先這里再明確一下,所有的版本控制系統(tǒng),其實只能跟蹤文本文件的改動,比如TXT文件,網(wǎng)頁,所有的程序代碼等等,Git也不例外。版本控制系統(tǒng)可以告訴你每次的改動,比如在第5行加了一個單詞“Linux”,在第8行刪了一個單詞“Windows”。而圖片、視頻這些二進制文件,雖然也能由版本控制系統(tǒng)管理,但沒法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是只知道圖片從100KB改成了120KB,但到底改了啥,版本控制系統(tǒng)不知道,也沒法知道。

不幸的是,Microsoft的Word格式是二進制格式,因此,版本控制系統(tǒng)是沒法跟蹤Word文件的改動的,前面我們舉的例子只是為了演示,如果要真正使用版本控制系統(tǒng),就要以純文本方式編寫文件

因為文本是有編碼的,比如中文有常用的GBK編碼,日文有Shift_JIS編碼,如果沒有歷史遺留問題,強烈建議使用標準的UTF-8編碼,所有語言使用同一種編碼,既沒有沖突,又被所有平臺所支持

新建一個文件code.txt,并添加一行內容,一定要放到gitTest目錄下(子目錄也行),用命令創(chuàng)建如下:

$ vi code.txt
# 查看文件內容可以是:
$ cat code.txt

下面把一個文件放到Git倉庫只需要兩步。
第一步,用命令git add告訴Git,把文件添加到倉庫:

$ git add code.txt

第二步,用命令git commit告訴Git,把文件提交到倉庫:

$ git commit -m '版本1'
[master (root-commit) 0c7efe4] 版本1
 1 file changed, 1 insertion(+)
 create mode 100644 code.txt
  • git commit命令,-m參數(shù)可有可無,但是為了理解管理,強烈建議加入版本說明
  • 可以多次add不同的文件,最后再執(zhí)行一次git commit
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

4.管理和回退

4.1 版本回退

Git的每一次commit都可以稱為“快照”,一旦你把文件改亂了,或者誤刪了文件,還可以從最近的一個commit恢復,然后繼續(xù)工作.

使用git log命令查看commit記錄:

commit e5fb29481a81fdfcdd65e4080ad99e04b27d8c0d (HEAD -> master)
Author: 侯萬 <136557493@qq.com>
Date:   Sun Apr 12 16:28:40 2020 +0800

    版本2

commit 0c7efe4b950670b18d47ad48c833c4f1ab4a0824
Author: 侯萬 <136557493@qq.com>
Date:   Sun Apr 12 16:26:54 2020 +0800

    版本1

git log命令顯示從最近到最遠的提交日志, 如果嫌輸出信息太多,看得眼花繚亂的,可以試試加上--pretty=oneline參數(shù):

$ git log --pretty=oneline
e5fb29481a81fdfcdd65e4080ad99e04b27d8c0d (HEAD -> master) 版本2
0c7efe4b950670b18d47ad48c833c4f1ab4a0824 版本1

這種e5fb...c0d一串字符,就是commit id版本號,和SVN不一樣,Git的commit id不是1,2,3……遞增的數(shù)字,而是一個SHA1計算出來的一個非常大的數(shù)字,用十六進制表示。

每提交一個新版本,實際上Git就會把它們自動串成一條時間線。如果使用可視化工具查看Git歷史,就可以更清楚地看到提交歷史的時間線:

0001.png

開始回到上一個版本,命令是:

$ git reset --hard HEAD^
HEAD is now at 0c7efe4 版本1

其中HEAD表示當前最新版本,HEAD^表示上一個版本,HEAD^^上上一個版本,也可以使用HEAD~1表示當前版本的前一個版本,HEAD~100表示當前版本的前100版本

此時,又想回到版本2,怎么辦?使用如下命令:版本號那么長,其實只復制前7/8位就可以

$ git reset --hard 版本號

如果還能看到之前git log記錄,就能復制到對應的版本號,如果看不到的話,使用下面命令查看操作記錄:

$ git reflog
0c7efe4 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
e5fb294 HEAD@{1}: commit: 版本2
0c7efe4 (HEAD -> master) HEAD@{2}: commit (initial): 版本1

能看到版本2的版本號是e5fb294,此時,我們使用下面的命令,就能再回到版本2:

$ git reset --hard e5fb294
HEAD is now at e5fb294 版本2

優(yōu)化顯示git log顯示:

$ git log --oneline

4.2 工作區(qū)和暫存區(qū)

工作區(qū)
工作區(qū)(Working Directory)是電腦中的目錄,比如我們的gitTest目錄,就是一個工作區(qū)

版本庫
版本庫(Repository):工作區(qū)里面的隱藏目錄.git就是git的版本庫.此文件夾下存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區(qū),還有分支信息、以及指向master的一個指針叫HEAD

0002.png

對比上圖,可以發(fā)現(xiàn):

  • git add實際上是把文件修改,添加到暫存區(qū)
  • git commit提交更改,實際就是把暫存區(qū)的所有內容,提交到當前分支

驗證練習,先對code.txt進行內容添加,再新增一個文件:code2.txt,此時,使用git status命令查看:

$ git status
On branch master
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:   code.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    code2.txt

no changes added to commit (use "git add" and/or "git commit -a")

Git非常情況告訴我們:code.txt被修改了,而code2.txt文件還沒有被添加過,所以狀態(tài)是Untracked

使用命令git add添加,并再次使用git status命令查看:

$ git add code.txt code2.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   code.txt
    new file:   code2.txt

此時,code.txt的修改和新文件code2.txt以及在暫存區(qū)(Stage)了。執(zhí)行git commit可以一次性把暫存區(qū)的所有修改,提交到分支。

$ git commit -m "版本3"
$ git status
On branch master
nothing to commit, working tree clean

可以看到,提交之后,工作區(qū)就是“干凈”的。

4.3 管理修改

這節(jié)證明git管理的是修改,而不是文件,這也是git相比其他版本控制系統(tǒng)優(yōu)秀的地方
第一步,對code.txt添加內容,并提交

$ vi code.txt
$ git add code.txt

此時git status顯示內容如下:

$ git status
On branch master
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:   code.txt

然后再繼續(xù)給code.txt添加一行內容,直接commit

$ vi code.txt
$ git commit -m "版本4"

此時按理來說,不管第一次修改,還是第二次修改,都應該提交的,但是執(zhí)行git status內容如下:

$ git status
On branch master
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:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

咦,怎么第二次的修改沒有被提交?顧一下操作過程:
第一次修改 > git add > 第二次修改 > git commit

結論:Git管理的是修改,當你用git add命令后,在工作區(qū)的第一次修改被放入暫存區(qū),準備提交,但是,在工作區(qū)的第二次修改并沒有放入暫存區(qū),所以,git commit只負責把暫存區(qū)的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。

此時,用git diff HEAD -- code.txt命令可以查看工作區(qū)和版本庫里面最新版本的區(qū)別:

$ git diff HEAD -- code.txt
diff --git a/code.txt b/code.txt
index 66f9219..ee99dfb 100644
--- a/code.txt
+++ b/code.txt
@@ -2,3 +2,4 @@ this is the first line
 this is the second line
 this is the third line
 this is the forth line
+this is the 5 linee

可見,第二次修改確實沒有被提交。可以繼續(xù)git addgit commit即可。

4.4 撤銷修改

繼續(xù)上面,第二次沒有真正的提交commit,此時想丟棄掉添加的內容,命令如下:

git checkout -- 文件名

git checkout -- file命令中的--很重要,沒有--就變成'創(chuàng)建一個新分支'的命令了

執(zhí)行情況如下:

$ git checkout -- code.txt 
$ git status
On branch master
nothing to commit, working tree clean

發(fā)現(xiàn)工作區(qū)已經(jīng)干凈了。

上面是修改文件之后,沒有git add的情況,下面我們修改文件,并git add到暫存區(qū):

$ vi code.txt
$ git add code.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   code.txt

此時,想要回退撤銷,需要下面的命令:(上面輸出也提示了)

git reset HEAD 文件名

那么執(zhí)行過程如下:

$ git reset HEAD code.txt   // 將文件從暫存區(qū),撤回工作區(qū)
$ git checkout -- code.txt  // 到工作區(qū)后,再丟棄掉修改
$ git status
On branch master
nothing to commit, working tree clean

結論

  • 在工作區(qū)撤銷(丟棄)命令是:git checkout -- fileName
  • 在暫存區(qū)撤銷的命令是:git reset HEAD fileName,此時文件在工作區(qū)了,然后再修改文件,或者直接丟棄git checkout -- fileName
  • 如果git commit了,想要撤銷,命令是git reset --hard 版本號,這個參加4.1版本回退章節(jié),(前提是沒有推送到遠程庫)

4.5 對比文件的不同

命令git diff是列出對比,可以來比較項目中任意兩個版本的差異。

$ git diff   // 列出當前沒有`git add`的所有修改的內容對比
$ git diff --cached  // 查看已緩存的改動 指已`git add`的內容
$ git git diff HEAD  // 查看已緩存的與未緩存的所有改動

具體某個文件的對比:git diff HEAD -- 文件名

# 列出`code.txt`文件和HEAD上的不同
$ git diff HEAD -- code.txt 

diff --git a/code.txt b/code.txt  // 這里a是指HEAD  b代表當前工作區(qū)的
index 66f9219..324317f 100644
--- a/code.txt  // ---代表減少的
+++ b/code.txt  // +++代表增加的
@@ -2,3 +2,4 @@ this is the first line
 this is the second line
 this is the third line
 this is the forth line
+the new line

兩個版本中具體某個文件的對比:
A版本號和B版本號某文件的對比:git diff A版本號 B版本號 -- 文件名
這版本和上個版本某文件的對比: git diff HEAD HEAD^ -- 文件名

$ git diff HEAD HEAD^ -- code.txt  // 對比這個版本和上個版本code.txt的不同

diff --git a/code.txt b/code.txt  // 這里a是指HEAD  b代表HEAD^
index 66f9219..01e1274 100644
--- a/code.txt
+++ b/code.txt
@@ -1,4 +1,3 @@
 this is the first line
 this is the second line
 this is the third line
-this is the forth line

如果你要查看當前的工作目錄與另外一個分支的差別,你可以用下面的命令執(zhí)行:

// 這會顯示你當前工作目錄與另外一個叫'test'分支的差別
$ git diff test
// 你當前工作目錄下的lib目錄與上次提交之間的差別(或者更準確的 說是在當前分支)
$ git diff HEAD -- ./lib

4.6 刪除文件

刪除文件,正常的命令刪除,或者右鍵刪除即可:

$ rm 文件名

刪除之后,要么撤銷,要么提交:

$ git add 文件名  # 提交刪除改動 到暫存區(qū)
$ git rm 文件名  # 提交刪除改動 到暫存區(qū)
$ git commit -m '刪除code.txt'  # 提交到當前分支

$ git checkout -- 文件名  # 撤銷刪除

4.7 本章總結

創(chuàng)建版本倉庫

$ git init  # 生成`.git` 目錄

版本創(chuàng)建

$ git add 文件/目錄  # 放到暫存區(qū)
$ git commit -m '版本說明信息'  # 創(chuàng)建一個版本記錄,只是記錄了修改

查看版本記錄

$ git log

版本回退

$ git reset --hard HEAD^  # HEAD指當前版本,幾個^代表前幾個版本
$ git reset --hard 版本序列號  

查看操作記錄

$ git reflog

工作區(qū)、版本庫、暫存區(qū)

$ 編輯文件都是在工作區(qū)
$ git add  # 把工作區(qū)的修改放入暫存區(qū)
$ git commit  # 把暫存區(qū)的修改一次性做一次版本記錄

撤銷修改

# 1.直接修改工作區(qū)的改動
$ git checkout -- 文件
# 2.修改已經(jīng)添加到暫存區(qū),但是沒有`commit`,下面2步
$ git reset HEAD 文件
$ git checkout -- 文件
# 3.已經(jīng)`commit`
$ git reset --hard HEAD^  # HEAD指當前版本,幾個^代表前幾個版本
$ git reset --hard 版本序列號  

對比文件不同

# 1.對比工作區(qū)和版本庫某個文件
$ git diff HEAD -- 文件
# 2.對比兩個版本中的文件
$ git diff HEAD HEAD^ -- 文件名

刪除文件

$ rm 文件名
$ git rm 文件名  # 添加到暫存區(qū)
$ git commit -m '刪除文件'  # 提交版本

5.分支管理

5.1 概念

直接查看官方介紹:https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%AE%80%E4%BB%8B

5.2 創(chuàng)建和合并分支

查看本地所有分支

$ git branch

下面創(chuàng)建一個分支dev并切換到其上進行工作

$ git checkout -b dev
$ git branch  # 查看分支

下面修改一個文件內容code.txt,并提交

$ vim code.text
$ git add code.txt
$ git commit -m 'dev分支提交'
$ git log --pretty=oneline  # 查看提交記錄

dev分支工作完成,切換回master分支:

$ git checkout master
Switched to branch 'master'
$ cat code.txt  # 查看code.text文件內容
$ git log --pretty=oneline  # 查看提交記錄

發(fā)現(xiàn)此時master分支沒有dev分支上改變的內容,需要合并分支:

$ git merge dev
Updating 5f63379..2667394
Fast-forward
 code.txt | 1 +
 1 file changed, 1 insertion(+)
 $ git log --pretty=oneline

上面的輸出里有Fast-forward,說明這次合并是快速模式,也就不是直接把master指向dev的當前提交,所以合并速度非???/p>

合并完成之后,可以放心的刪除dev分支了:

$ git branch -d dev  # 刪除dev分支
$ git branch  # 查看分支列表

本章小結:

  • 查看分支:git branch
  • 創(chuàng)建分支:git branch <name>
  • 切換分支:git checkout <name>
  • 創(chuàng)建+切換分支:git checkout -b <name>
  • 合并某分支到當前分支:git merge <name>
  • 刪除分支:git branch -d <name>

5.3 解決沖突

合并分支很多時候,并不是一帆風順的!

1.再創(chuàng)建一個dev分支,并修改文件code.txt

$ git checkout -b dev
$ git branch  # 查看分支
$ vim code.txt 
$ git add code.txt 
$ git commit -m 'dev分支提交2'
$ git log --pretty=oneline

2.切換回master,并修改文件code.txt

$ git checkout master 
$ vim code.txt
$ git add code.txt 
$ git commit -m 'master分支提交'
$ git log --pretty=oneline

3.合并dev分支到master,能看下面自動合并錯誤,產生了合并沖突merge confict

$ git merge dev
Auto-merging code.txt
CONFLICT (content): Merge conflict in code.txt
Automatic merge failed; fix conflicts and then commit the result.

4.上面已經(jīng)提示了沖突文件,當然也可以使用命令查看沖突文件:

$ git status  # 會顯示出沖突的文件
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

5.解決沖突,刪除git給標識出來的沖突內容,手動融合

$ vim code.txt  # 打開沖突文件
# 沖突內容會用下面的標識
<<<<<<< HEAD
=======
>>>>>>> dev
$ git add code.txt  # 解決沖突后,提交一下
$ git commit -m '解決分支合并沖突'
$ git log --pretty=oneline

6.查看分支合并記錄:

$ git log --graph
$ git log --graph --pretty=oneline

7.最后可以刪除dev分支即可

$ git branch -d dev
$ git branch 

5.4 分支管理策略

通常,合并分支時,如果可能,git會用Fast-forward模式,但是有些快速合并不能成功并且沒有沖突,這個時候git會合并之后并做一次新的提交??!這種模式下,刪除分支后,會丟掉分支信息??!

1.創(chuàng)建切換到dev分支下

$ git checkout -b dev
$ git branch

2.新建一個文件code3.txt,編輯內容,并做一個commit

$ vim code3.txt
$ ls
$ git add code3.txt
$ git commit -m '創(chuàng)建文件code3.txt'
$ git log --pretty=oneline

3.切換到master分支,編輯code.txt并進行一個提交

$ git checkout master
$ git log --pretty=oneline
$ vim code.txt
$ git add code.txt
$ git commit -m '添加新行'
$ git log --pretty=oneline

4.合并dev分支的內容到master分支,出現(xiàn)下面的提示

$ git merge dev
此時會有和輸入彈框,用來說明合并分支的信息,如果提交空說明會終止提交,鍵盤I開始輸入,esc輸入完畢,進入命令模式,輸入:wq即可退出,git會自動幫提交commit
$ git log --pretty=oneline

附帶輸入完畢退出之后的git提交信息:發(fā)現(xiàn)它的策略是:recursive strategy

$ git merge dev
Merge made by the 'recursive' strategy.
 code3.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 code3.txt

5.先查看提交記錄,帶分支合并圖,刪除dev分支

$ git log --graph --pretty=oneline
$ git branch -d dev

如果要強制禁用Fast-forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息

1.創(chuàng)建并切換到dev分支

$ git checkout -b dev

2.修改code.txt內容,并提交一個commit

$ vim code.txt
$ git add code.txt
$ git commit -m 'dev添加新行'

3.切換到master分支

$ git checkout master

4.合并dev分支到master分支,禁止使用fast-forward模式,注意參數(shù)--no-ff -m

$ git merge --no-ff -m '禁用fast-forward合并' dev
Merge made by the 'recursive' strategy.
 code.txt | 1 +
 1 file changed, 1 insertion(+)

-m參數(shù)把合并信息填寫進去,git會自動加到commit信息

5.合并后,查看分支歷史,可以看到,不使用fast-forward模式,就會能在歷史記錄中看到合并記錄

$ git log --pretty=oneline --graph 

6.最后可以刪除dev分支即可

$ git branch -d dev
$ git branch 

5.5 bug分支

軟件開發(fā)中,bug很多,需要修改,在git中,由于分支是如此強大,所以每個bug都可以通過一個新的臨時分支來修復,修復后,合并分支,然后將臨時分支閃出去。

1.當你接到一個修復代號為001的bug任務,很自然地,你想創(chuàng)建一個分支bug-001來修復它,但是,等等,當前正在dev上進行的工作還沒有提及:

$ git checkout -b dev
$ vim code3.txt
$ git status
On branch dev
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:   code3.txt

no changes added to commit (use "git add" and/or "git commit -a")

并不是你不想提交,而是工作只進行到一半,還沒法提交,預計完成還需要1天時間,但是必須在兩個小時內修改bug,怎么辦呀?

2.Git還提供一個stash功能,可以把當前工作現(xiàn)場儲藏起來,等以后恢復現(xiàn)場后,繼續(xù)工作

$ git stash
Saved working directory and index state WIP on dev: 265f7f3 禁用fast-forward合并
$ git status
On branch dev
nothing to commit, working tree clean

3.首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master上創(chuàng)建臨時分支

$ git checkout master
$ git checkout -b bug-001
$ git branch

4.現(xiàn)在修改bug,比如刪掉文件code.txt內的一行文本

$ ls
$ vim code.txt
$ git add code.txt
$ git commit -m '修復001bug'

5.修改完成后,回到master分支,并完成合并,最后刪除bug-001分支

$ git checkout master 
# 注意,為了保留bug分支合并記錄,沒使用`fast-forward`模式
$ git merge --no-ff -m '修復bug001' bug-001 
$ git branch -d bug-001
$ git branch
$ git log --pretty=oneline --graph 

6.現(xiàn)在bug-001修復完成,是時候回到dev分支繼續(xù)干活了

$ git checkout dev
$ git status
On branch dev
nothing to commit, working tree clean

7.工作區(qū)是干凈的,剛剛的工作現(xiàn)場存哪去了?使用命令查看一下:

$ git stash list
stash@{0}: WIP on dev: 265f7f3 禁用fast-forward合并

工作現(xiàn)場還在,Git把stash內容存在某個地方了,但是需要恢復一下.

$ git stash pop  # 恢復工作現(xiàn)場
On branch dev
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:   code3.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (83885218b343475028379e6c095226be86e2f816)
$ git status  # 發(fā)現(xiàn)已回到之前的工作代碼狀態(tài)

小結:
修改bug時,我們會通過新建bug分支進行修復,然后合并,最后刪除。
當手頭工作沒有完成時,先把工作現(xiàn)場git stash一下,然后去修bug。修復完成后,再git stash pop回到工作現(xiàn)場。

5.6 本章總結

  • 分支操作的基本命令
  • 查看分支git branch
  • 創(chuàng)建分支git branch 分支名
  • 切換分支git checkout 分支名
  • 創(chuàng)建并切換分支git checkout -b 分支名
  • 合并分支git merge 分支名
  • 刪除分支git branch -d 分支名
  • 分支沖突
  • 兩個分支都有新的提交記錄,并且修改是同一個文件
  • 手動融合沖突內容<<<<<<<,=======,>>>>>>>
  • 分支管理策略
  • 合并的時候,如果可以,執(zhí)行快速合并fast-forward
  • 禁止快速合并git merge --no-ff -m '提交內容' 分支名
  • bug分支
  • 存儲工作現(xiàn)場git stash
  • 切換到bug所在分支,并創(chuàng)建一個臨時分支,完成修復,合并分支
  • 回到工作現(xiàn)場git stash pop

6.遠程相關

6.1 創(chuàng)建倉庫

這里不同的Git平臺不太一樣,自行查即可。比如Github,碼云

6.2 添加SSH賬戶

SSH的簡單實用

6.3 克隆項目

看到克隆地址,一般是兩種方式:SSHHttps

$ cd xx  # cd到合適的目錄
$ git clone 倉庫地址

6.4 推送分支

1.項目克隆到本地之后,執(zhí)行下面命令創(chuàng)建分支dev

$ git checkout -b dev
$ git branch

2.創(chuàng)建一個文件,并提交一個版本

$ vim view.py
$ ls
$ git add *
$ git commit -m '創(chuàng)建index視圖'

3.推送到遠程服務器:推送分支就是把該分支上的所有本地提交推送到遠程庫,推送時要指定本地分支,這樣,git就會把該分支推送到遠程庫對應的分支上

$ git push origin 分支名  # origin 代表遠程庫
# 例如
$ git push origin dev

6.5 跟蹤遠程分支

將本地分支跟蹤服務器分支

$ git branch --set--upstream-to=origin/遠程分支名 本地分支名
# 例如
$ git branch --set-upstream-to=origin/dev dev

主要是為了分支代碼的同步,讓遠程分支或者本地分支有新版本時,能及時拉取和同步,比如本地更改以后,提交到遠程分支

$ vim view.py
$ git add view.py
$ git commit -m '提交新內容'
$ git status  # 會提示本地分支領先遠程分支
$ git push  # 推送到遠程

6.6 從遠程分支拉取代碼

當別人提交了代碼到遠程分支上,拉取代碼

$ git pull origin 遠程分支名
# 例如
$ git pull origin dev

使用上面命令會把遠程分支dev上的代碼下載合并到本地所在分支。

7.高頻命令

如下所示:

# 查看所有遠程分支
$ git branch -r
# 創(chuàng)建一個本地分支dev, 并切換到該分支
$ git checkout -b dev
# 切換到名字為origin/test的遠程分支
$ git checkout --track origin/test
# 創(chuàng)建一個名字為dev的本地分支, 并將該本地分支跟蹤到名字為origin/test的遠程分支
$ git checkout -b dev --track origin/test

Git的gitignore文件不生效辦法

$ git rm -r --cached .
$ git add .
$ git commit -m 'update .gitignore'

Git強制分支覆蓋Maser分支
假設分支test覆蓋到Master.方法一:

# 將test分支強制(-f)推送到主分支master
$ git push origin test:master -f

方法二: (假設當前位于test分支)

$ git checkout master  # 將當前分支切換到主分支
$ git reset --hard test  # 將主分支重置為test分支
$ git push origin master -f  # 將重置后的master分支強制推送到遠程倉庫

Git回滾某個版本并同步到遠程

$ git reset --hard xxxx   # xxx是git版本號
$ git push origin master -f  # 強制提交到遠程

如果你在遠端已經(jīng)建立過分支,本地創(chuàng)建并跟蹤這個遠程分支

# devName是本地分支  origin/devName是遠端分支
$ git checkout -b devName origin/devName

從某一個commit開始創(chuàng)建本地分支

git checkout commitId -b 本地branchName

# 推送到遠程,遠程此時還沒有這個分支的情況下
git push origin 本地branchName

提交本地代碼到新分支
背景:從branchA分支拉了一份代碼,做了一些修改,但是不想提交到branchA分支,想新建一個分支branchB保存代碼。

$ git add .
$ git commit -m "update"
$ git push origin branchA:branchB
# 倉庫中原本沒有branchB,提交后會生成新分支branchB,并將本地基于branchA修改的代碼提交到branchB中.

# 切換到新分支
$ git checkout -b branchB origin/branchB

但是上面的操作會讓branchA多一條commit,可以回退一下即可git reset --hard commit_id

移除本地所有未跟蹤的文件

$ git clean -xfd
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1. 安裝和初始化設置 git config --global name "your name"git confi...
    午覺不眠Orz閱讀 466評論 0 0
  • 前言 Git在平時的開發(fā)中經(jīng)常使用,整理Git使用全面的梳理。 基本內容 開始之前 請自行準備好Git工具以及配置...
    weir_will閱讀 310評論 0 1
  • 1、git將文件添加到.gitignore文件中不生效? 原因:在加入.gitignore前該文件已經(jīng)被追蹤。gi...
    瘋狂藝人閱讀 269評論 0 0
  • 初始化git . git init 初始化一個git resposity git add 添加到暫存區(qū)(紅色表...
    maskwang520閱讀 607評論 0 2
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,889評論 28 54

友情鏈接更多精彩內容