一起來看看史上最詳細Git使用教程

一起來看看史上最詳細Git使用教程

git是世界上最先進的分布式版本控制系統,克隆一個項目的速度非常快

每個開發都可以從master上克隆一個本地版本庫,就算沒有網絡,也可以提交代碼到本地倉庫、查看log、創建項目分支等等

每個版本庫都可以創建無限個分支,分支是個完整的目錄,且這個目錄擁有完整的實際文件

推薦(免費):git

一、安裝

網上搜一下安裝教程,這里就不介紹了

安裝完成后,在開始菜單里找到“Git”->“Git Bash”,彈一個類似命令行窗口的東西,就說明Git安裝成功

接著需要設置一下機器信息,這臺機器上的所有Git倉庫都會使用這個配置

$?git?config?--global?user.name?"username" $?git?config?--global?user.email?"email@example.com"

二、創建版本庫

1、創建一個空目錄(最好不要包含中文)

$?mkdir?mymenu $?cd?mymenu $?pwd /Users/hxk/mymenu

pwd命令顯示當前目錄

2、初始化倉庫

git init命令把這個目錄變成git可以管理的倉庫

$?git?init Initialized?empty?Git?repository?in?/Users/hxk/mymenu/.git/

初始化了一個空的倉庫,目錄下多了.git目錄

系統自動創建了唯一一個master分支

版本控制系統只能跟蹤文本文件的改動,且編碼方式是utf-8

三、文件的基本操作

創建一個test.txt文件,內容如下:

Hello?World

1、添加文件到倉庫

$?git?add?readme.txt

2、提交文件到倉庫

$?git?commit?-m?"a?new?file"

-m后面輸入的是本次提交的說明,提交成功后會顯示:

1 file changed:1個文件被改動(我們新添加的readme.txt文件);

2 insertions:插入了兩行內容(readme.txt有兩行內容)。

為什么Git添加文件需要add,commit一共兩步呢?因為commit可以一次提交很多文件,所以你可以多次add不同的文件

$?git?add?file1.txt $?git?add?file2.txt?file3.txt $?git?commit?-m?"add?3?files."

如果提交的備注寫錯了,可以用以下命令修改剛剛提交的備注

$?git?commit?--amend

3、修改文件

將test.txt文件修改如下:

Hello?World?ABC

提交

$?git?add?test.txt $?git?commit?-m?"append?ABC"

每次commit都會生成一個“快照”

4、查看歷史記錄

$?git?log commit?1094adb7b9b3807259d8cb349e7df1d4d6477073?(HEAD?-&gt;?master) Author:?hxk?<hxk> Date:???Fri?July?20?21:06:15?2018?+0800  ????append?ABC  commit?eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 Author:?hxk?<hxk> Date:???Fri?July?20?20:59:18?2018?+0800  ????a?new?file</hxk></hxk>

git log顯示最近到最遠的提交日志,我們可以看到兩次提交,最后一次是append ABC

git的版本號是用SHA1計算出來的一個16進制數

如果嫌輸出信息太多,可以加上–pretty=oneline

$?git?log?--pretty=oneline 1094adb7b9b3807259d8cb349e7df1d4d6477073?(HEAD?-&gt;?master)?append?ABC eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0?a?new?file

5、回退歷史版本

$?git?reset

首先,Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,也就是最新的提交1094adb…,上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。

回退上一版本

$?git?reset?--hard?HEAD^ HEAD?is?now?at?eaadf4e?a?new?file

?這時再次查看歷史版本

$?git?log commit?eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 Author:?hxk?<hxk> Date:???Fri?July?20?20:59:18?2018?+0800  ????a?new?file</hxk>

之前那個版本已經看不到了,這時如果想回到之前那個版本,需要知道版本號,git內部有個指向當前版本的head指針,將指針從當前版本指回去,所以git回退版本特別快

$?git?reset?--hard?1094adb7

?6、查看歷史命令

要是不記得剛才的版本號了,可以使用以下命令:

$?git?reflog

7、查看狀態

$?git?status

四、工作區和暫存區

Git和SVN的一個不同之處就是有暫存區的概念

名詞解釋:

工作區(Working Directory):指的是在電腦里能看到的目錄,比如mymenu文件夾就是一個工作區

版本庫(Repository):.git目錄,Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。

?

git add是把需要提交的文件添加到暫存區

一起來看看史上最詳細Git使用教程

git commit是把暫存區的所有內容提交到當前分支

————————-測試一下————————–

在工作區新增一個testfile文本文件

先用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:???test.txt  Untracked?files: ??(use?"git?add?<file>..."?to?include?in?what?will?be?committed)  ????testfile  no?changes?added?to?commit?(use?"git?add"?and/or?"git?commit?-a")</file></file></file>

Git非常清楚地告訴我們,test.txt被修改了,而testfile還從來沒有被添加過,所以它的狀態是Untracked。

將testfile提交后再查看狀態

$?git?status On?branch?master Changes?to?be?committed: ??(use?"git?reset?HEAD?<file>..."?to?unstage)  ????new?file:???testfile ????modified:???test.txt</file>

提交后沒有對工作區進行修改的話,查看狀態,工作區是干凈的

$?git?status On?branch?master nothing?to?commit,?working?tree?clean

——————————-測試結束————————————

五、修改

1、管理修改

那么,為什么說git比svn優秀呢?因為git跟蹤并管理的是修改,而不是文件

修改test.txt文件內容,添加一行

$?cat?test.txt Hello?World?ABC This?is?the?second?line

然后添加文件

$?git?add?test.txt

再次修改test.txt

$?cat?test.txt Hello?World?ABC This?is?the?second?line This?is?the?third?line

提交

$?git?commit?-m?"test?add?lines"

這時我們發現,第二次的修改未提交,這是為什么呢?

第一次修改–>git add–>第二次修改–>git commit

add將工作區的修改存入暫存區,但是第二次修改并未存入暫存區,git commit只負責把暫存區的修改提交,所以正確的順序應該是:

第一次修改 –> git add –> 第二次修改 –> git add –> git commit

提交后,查看工作區和版本庫里面最新版本的區別:

$?git?diff?HEAD?--?test.txt

2、撤銷修改

1)丟棄工作區的修改?git checkout — file(–很重要,沒有–,就變成了“切換到另一個分支”的命令):

$?git?checkout?--?test.txt

命令git checkout — test.txt意思就是,把test.txt文件在工作區的修改全部撤銷,這里有兩種情況:

一種是test.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;

一種是test.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。

總之,就是讓這個文件回到最近一次git commit或git add時的狀態。

2)把暫存區的修改撤銷掉(unstage),重新放回工作區 ?git reset HEAD

$?git?reset?HEAD?test.txt Unstaged?changes?after?reset: M????test.txt

git reset命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。

?3、刪除文件

工作區中刪除文件

$?rm?test.txt

一是要從版本庫中刪除該文件,那就用命令git rm刪掉,并且git commit:

$?git?rm?test.txt $?git?commit?-m?"remove?test.txt"

二是刪錯了,因為版本庫里還有呢,所以可以很輕松地把誤刪的文件恢復到最新版本:

$?git?checkout?--?test.txt

git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。

PS:?手動刪除文件,然后使用git rm 和git add效果是一樣的。

六、分支管理

1、創建與合并分支

每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git里,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:

一起來看看史上最詳細Git使用教程

?

每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長。

當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

一起來看看史上最詳細Git使用教程

?

你看,Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:

一起來看看史上最詳細Git使用教程

?

假如我們在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合并:

一起來看看史上最詳細Git使用教程

?

所以Git合并分支也很快!就改改指針,工作區內容也不變!

合并完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:

一起來看看史上最詳細Git使用教程

?

————————————測試開始—————————————————

1)創建分支 ? git branch

? ? ?切換分支 ?git checkout

首先,我們創建dev分支,然后切換到dev分支:

$?git?checkout?-b?dev Switched?to?a?new?branch?'dev'

git checkout命令加上-b參數表示創建并切換,相當于以下兩條命令:

$?git?branch?dev $?git?checkout?dev Switched?to?branch?'dev'

2)查看分支 ?git branch

然后,用git branch命令查看當前分支:

$?git?branch *?dev ??master

git branch命令會列出所有分支,當前分支前面會標一個*號。

然后,我們就可以在dev分支上正常提交,比如對test.txt做個修改,再提交,dev分支的工作完成后,我們就可以切換回master分支:

$?git?checkout?master Switched?to?branch?'master'

切換回master分支后,再查看一個test.txt文件,剛才添加的內容不見了!因為那個提交是在dev分支上,而master分支此刻的提交點并沒有變:

一起來看看史上最詳細Git使用教程

?

3)合并某個分支到當前分支 ?git merge

現在,我們把dev分支的工作成果合并到master分支上:

$?git?merge?dev

git merge命令用于合并指定分支到當前分支。合并后,再查看test.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。

4)刪除分支 ?git branch -d

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

$?git?branch?-d?dev Deleted?branch?dev?(was?b17d20e).

刪除后,查看branch,就只剩下master分支了:

$?git?branch *?master

因為創建、合并和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合并后再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全。?

2、解決沖突

創建一個新的分支feature1?

$?git?checkout?-b?feature1 Switched?to?a?new?branch?'feature1'

?將test.txt修改了一下,加上“AND Simple”,在feature1分支上提交

Hello?World?ABC This?is?the?second?line?AND?Simple

切換到master分支

$?git?checkout?master

在master分支上,將test.txt的最后一行加上“& Simple”,提交:

Hello?World?ABC This?is?the?second?line?&amp;?Simple

當兩個分支都分別有了新的提交,如下圖所示:

一起來看看史上最詳細Git使用教程

?

這種情況下無法進行快速合并,只能試圖把各自的修改合并起來,這樣有可能會造成沖突:

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

這時我們必須手動解決沖突后再提交,git status可以查看沖突的文件:

$?git?status On?branch?master Your?branch?is?ahead?of?'origin/master'?by?2?commits. ??(use?"git?push"?to?publish?your?local?commits)  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:???test.txt  no?changes?added?to?commit?(use?"git?add"?and/or?"git?commit?-a")</file>

?

查看test.txt文件的內容:

Hello?World?ABC &gt;&gt;&gt;&gt;&gt;&gt;?feature1

Git用>>>>>>標記出不同分支的內容,我們修改如下后保存:

This?is?the?second?line?and?Simple

再提交

$?git?add?test.txt? $?git?commit?-m?"conflict?fixed" [master?cf810e4]?conflict?fixed

現在,master分支和feature1分支變成了下圖所示:

一起來看看史上最詳細Git使用教程

?

用git?log?–graph?–pretty=oneline?–abbrev-commit可以看到分支的合并情況,包括分支合并圖(–graph)、一行顯示(–pretty=oneline)、提交校驗碼縮略(–abbrev-commit)顯示:

$?git?log?--graph?--pretty=oneline?--abbrev-commit *???cf810e4?(HEAD?-&gt;?master)?conflict?fixed |?? |?*?14096d0?(feature1)?AND?simple *?|?5dc6824?&amp;?simple |/?? *?b17d20e?branch?test *?d46f35e?(origin/master)?remove?test.txt *?b84166e?add?test.txt *?519219b?git?tracks?changes *?e43a48b?understand?how?stage?works *?1094adb?append?ABC *?eaadf4e?a?new?file

最后,刪除feature1分支:

$?git?branch?-d?feature1 Deleted?branch?feature1?(was?14096d0).

3、分支管理策略

通常,合并分支時,Git會用快速合并模式(Fast forward),但這種模式下,刪除分支后,會丟掉分支信息。

如果用普通合并模式,從分支歷史上就可以看出分支信息。

那么,如何使用普通合并模式呢?我們可以用–no-ff參數

$?git?merge?--no-ff?-m?"merge?with?no-ff"?dev

不使用Fast forward模式,merge后就像這樣:如下圖所示:

一起來看看史上最詳細Git使用教程

?

分支策略

master分支是最穩定的,只能用于發布新版本,平時不能在上面進行開發,要在新建的分支上進行開發,比如dev,這時dev是不穩定的,到產品1.0發布時,將dev分支和master分支合并,在master分支上發布1.0版本。

所以團隊合作的分支看起來就像這張圖一樣:

一起來看看史上最詳細Git使用教程

?

4、bug分支

修復bug時,我們會創建一個bug分支進行修復,修復完合并,刪除分支。

如果手頭上有未完成的工作,先把工作現場git stash一下:

$?git?stash Saved?working?directory?and?index?state?WIP?on?dev:?f52c633?add?merge

查看下工作區是否干凈

$?git?status

等bug修復完分支刪除后,我們先查看下stash

$?git?stash?list stash@{0}:?WIP?on?dev:?f52c633?add?merge

恢復工作現場

1)用git stash apply恢復,但是恢復后,stash內容并不刪除,你需要用git stash drop來刪除

? ? ?可以多次stash,恢復指定的stash;

$?git?stash?apply?stash@{0}

2)用git stash pop,恢復的同時把stash內容也刪了:

$?git?stash?pop

5、Feature分支

開發一個新功能,需要新建一個分支。

如果這個功能還未合并就要取消,要使用-D強行刪除

$?git?branch?-D?分支名

6、多人協作

當你從遠程克隆時,git自動把本地master分支和遠程master分支對應起來,遠程倉庫默認名為origin

1)查看遠程庫的信息

$?git?remote

查看遠程庫的詳細信息

$?git?remote?-v

2)推送分支

將本地master分支推送到遠程庫

如果不推送到遠程,本地分支對于其它人就是不可見的

$?git?push?origin?master

3)抓取分支

如果本地分支推送到遠程庫的文件有沖突,推送失敗,我們就得先從遠程庫中抓取最新的提交合并到本地,解決沖突再提交。

$?git?pull

如果git pull報錯:沒有指定本地分支與遠程分支的鏈接,我們就要手動設置一下

git?branch?--set-upstream-to=origin/?本地分支名

4)Rebase

rebase操作可以把本地未push的分叉提交歷史整理成直線;

目的是使得我們在查看歷史提交的變化時更容易,因為分叉的提交需要三方對比。

$?git?rebase

和merge的對比示意圖如下:

merge–>

一起來看看史上最詳細Git使用教程

rebase–>?

一起來看看史上最詳細Git使用教程

七、標簽管理

切換到需要打標簽的分支上

1)新建一個標簽(默認為HEAD,也可以指定一個commit id)

創建帶有說明的標簽,用-a指定標簽名,-m指定說明文字

$?git?tag? $?git?tag??<commit> $?git?tag?-a??-m?"備注"</commit>

2)查看標簽

標簽不是按時間順序列出,而是按字母排序的。

git tag查看所有標簽,用git show 標簽名查看指定的某個標簽信息

$?git?tag $?git?show?

PS:標簽總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那么在這兩個分支上都可以看到這個標簽。

3)刪除標簽

創建的標簽都只存儲在本地,不會自動推送到遠程,所以打錯的標簽可以在本地安全刪除;

$?git?tag?-d?

如果標簽已經推送到遠程,要先從本地刪除,再從遠程刪除

$?git?tag?-d? $?git?push?origin?:refs/tags/

4)推送標簽到遠程

推送某個標簽到遠程?git push origin

推送全部尚未推送到遠程的本地標簽?git push origin –tags

$?git?push?origin? $?git?push?origin?--tags

以上。

To be continued…

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享