Git的學(xué)習(xí)(寫給自己的教程)


Git(分布式版本控制系統(tǒng))

Git

Git是一個開源的分布式版本控制系統(tǒng),可以有效、高速地處理從很小到非常大的項目版本管理。


Git的特點

分布式相比于集中式的最大區(qū)別在于開發(fā)者可以提交到本地,每個開發(fā)者可以通過克?。╣it clone)在本地機器上拷貝一個完整的Git倉庫。


優(yōu)點

1.適合分布式開發(fā),強調(diào)個體。
2.公共服務(wù)器壓力和數(shù)據(jù)量都不會太大。
3.速度快、靈活。
4.任意兩個開發(fā)者之間可以很容易的解決沖突。
5.離線工作。


缺點

1.學(xué)習(xí)周期相對而言比較長。
2.代碼保密性差,一旦開發(fā)者把整個庫克隆下來就可以完全公開所有代碼和版本信息。


Git的一些操作及相關(guān)概念

創(chuàng)建版本庫:git init

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

  • 首先,選擇一個合適的地方,創(chuàng)建一個空目錄(目錄名不要包含中文):
    例如:

    然后在該文件夾里右鍵單擊選擇Git Bush Here,在彈窗中輸入:
$ mkdir learngit
$ cd learngit
$ pwd

pwd命令用于顯示當(dāng)前目錄。我的倉庫位于/e/Git/the first repository/learngit

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



    (這是一個空倉庫,當(dāng)前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,不能亂動。如果沒有看到.git目錄,那是因為這個目錄默認(rèn)是隱藏的,用ls -ah命令就可以看見。)


把文件添加到版本庫

所有的版本控制系統(tǒng),其實只能跟蹤文本文件的改動,比如TXT文件,網(wǎng)頁,所有的程序代碼等等,Git也不例外。版本控制系統(tǒng)可以告訴你每次的改動,而圖片、視頻這些二進制文件,雖然也能由版本控制系統(tǒng)管理,但沒法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是只知道圖片的占用內(nèi)存大小變了,但到底改了啥,版本控制系統(tǒng)不知道,也沒法知道。
(windows系統(tǒng)不要使用自帶文本軟件,可使用Notepad++代替)
先編寫一個readme.text文件,內(nèi)容如下:

Git is a version control system.
Git is a free software.

把這個文件放到learngit目錄下(子目錄也行),即一定要放到你的Git倉庫里面。接下來添加命令使文件添加到倉庫里面:

  • 第一步,用命令git add將文件添加到倉庫(可以同時將多個文件添加進倉庫):
    $ git add readme.text

    (沒有顯示其他東西就說明成功了)
  • 第二步,用命令git commit將文件提交到倉庫:
    $ git commit -m"wrote a readme file"

    -m后面輸入的是本次提交的說明,可以輸入任意內(nèi)容,方便自己能從歷史記錄里找到自己的改動記錄。
    git commit命令執(zhí)行成功后會有:1 file changed:1個文件被改動(新添加的readme. text文件);2 insertions:插入了兩行內(nèi)容(readme. text有兩行內(nèi)容)。

修改倉庫里的文件

在前面已經(jīng)添加了readme. text文件的基礎(chǔ)上,我們可以對文件進行修改,改成如下內(nèi)容:

Git is a distributed version control system.
Git is a free software. 

用命令git status查看結(jié)果:


git status命令可以讓我們看到倉庫當(dāng)前的狀態(tài),這里顯示readme. text已經(jīng)被修改過了,但是這個修改還沒有提交。
用命令git diff可以查看文件具體修改的內(nèi)容:

這里顯示我們在第一行添加了distributed。
接下來就是提交修改的文件,提交修改的文件和之前提交新文件的步驟是一樣的:

  • 第一步git add
    用命令git status查看倉庫當(dāng)前狀態(tài):

    這里顯示將要被提交的修改包括了readme. text
  • 第二步git commit
    提交后,再用命令git status查看倉庫當(dāng)前狀態(tài):

    這里顯示沒有需要提交的修改,工作目錄是干凈的。

查看歷史記錄

用命令git log可以查看提交日志:


這里可以看到最近的一次是add distributed,最早的一次是wrote a readme file
可以試試加上--pretty=oneline參數(shù)使顯示的更簡潔:

(這里的一串?dāng)?shù)字和字母的組合是commit id即版本號,例如33b2d9c···就是wrote a readme file的版本號)
每提交一個新版本,Git就會把它們自動串成一條時間線。


版本回退

在Git中,用HEAD表示當(dāng)前版本,上一個版本是HEAD^,上上個版本是HEAD^^。如果版本過多可以用HEAD~number,例如往上100個版本:HEAD~100。
可以使用命令git reset使版本從add distributed回退到wrote a readme file


可以看到版本已經(jīng)退回到了wrote a readme file
使用命令cat可以查看readme.text是否真的退回到了上一個版本:

使用命令git log再次查看當(dāng)前版本庫的狀態(tài):

可以看到版本庫中只剩下第一個版本了。
現(xiàn)在可以使用add distributed的版本號回到add distributed的版本:

這樣版本又回到了add distributed
如果不記得版本號而且還把彈窗關(guān)了,可以使用命令git reflog來查找之前的命令:

這樣就找到之前的版本號了。


工作區(qū)與暫存區(qū)

工作區(qū)(Working Directory)

就是能在電腦里面看到的目錄,比如這里的learngit文件夾就是一個工作區(qū)

版本庫(Repository)

工作區(qū)有一個隱藏目錄.git,這個不算工作區(qū),而是Git的版本庫。

暫存區(qū)(Temporary Area)

Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區(qū),還有Git自動創(chuàng)建的第一個分支master,而前面用到的HEAD命令就是指向master的指針。


在之前的提交文件到倉庫的過程中:用git add把文件添加進去,實際上就是把文件修改添加到暫存區(qū);用git commit提交更改,實際上就是把暫存區(qū)的所有內(nèi)容提交到當(dāng)前分支。因為創(chuàng)建Git版本庫時,Git自動創(chuàng)建了唯一一個master分支,所以現(xiàn)在,git commit就是往master分支上提交更改??梢院唵卫斫鉃椋枰峤坏奈募薷耐ㄍǚ诺綍捍鎱^(qū),然后,一次性提交暫存區(qū)的所有修改。


管理修改

Git管理的是修改,而不是文件。
舉個例子
readme.text中添加一行:
Git has a mutable index called stage.
然后添加并查看狀態(tài):


然后再修改一次readme.text的內(nèi)容:
刪除第一行的distributed


再提交:

查看狀態(tài):

可以看到第二次的修改并沒有被提交。
提交后,用git diff HEAD -- readme.text命令可以查看工作區(qū)和版本庫里面最新版本的區(qū)別:

如果想要第二次修改也被提交,則可以在第二次修改后git add,和第一次修改一起git commit;或者在第一次修改被提交之后,再將第二次修改git add,然后單獨將第二次修改git commit:


撤銷修改

我們可以使用git checkout -- <file>來撤銷工作區(qū)(還沒有git add)的修改。
命令git checkout -- readme.text意思就是,把readme.text文件在工作區(qū)的修改全部撤銷,這里有兩種情況:

  • 一種是readme.text自修改后還沒有被放到暫存區(qū),現(xiàn)在,撤銷修改就回到和版本庫一模一樣的狀態(tài);
  • 一種是readme.text已經(jīng)添加到暫存區(qū)后,又作了修改,現(xiàn)在,撤銷修改就回到添加到暫存區(qū)后的狀態(tài)。

總之,就是讓這個文件回到最近一次git commitgit add時的狀態(tài)。
先在readme.text里面加一句話:
oh my god!


此時并沒有git add,我們可以使用命令git checkout -- readme.text進行撤銷:

如果不小心把這句話已經(jīng)git add到暫存區(qū)了(但是還沒有git commit):

可以使用命令git reset HEAD <file>把暫存區(qū)的修改重新放回工作區(qū):

然后再用git checkout -- readme.text撤銷工作區(qū)的修改;

如果已經(jīng)將修改git commit到版本庫里了,就使用版本回退的方法。(前提是沒有推送到遠程倉庫)


刪除文件

我們可以使用命令rm來刪除文件。
首先,先建立一個新的文件new.text并且提交:


現(xiàn)在使用命令rm new text刪除文件:

此時只是在工作區(qū)中執(zhí)行了刪除new.text文件的命令,但是文件依然存在于版本庫中,如果想要在版本庫中刪除new.text文件,那就用命令git rm刪掉,并且git commit

假如是不小心誤刪了這個文件(還沒有從版本庫里刪除),我們依然可以用命令git checkout來還原(即撤銷上一步操作)。(從來沒有被添加到版本庫就被刪除的文件,是無法恢復(fù)的?。?p>


遠程倉庫

遠程倉庫相當(dāng)于是一個服務(wù)器,你可以推送自己的東西到這個服務(wù)器上,同時也能拉取別人的推送。

創(chuàng)建遠程倉庫(在GitHub上創(chuàng)建)

  • 第1步:創(chuàng)建SSH Key。在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsaid_rsa.pub這兩個文件,如果已經(jīng)有了,可直接跳到下一步。如果沒有,打開Shell(Windows下打開Git Bash),創(chuàng)建SSH Key
    $ ssh-keygen -t rsa -C "youremail@example.com"
    把郵件地址換成自己的郵件地址,然后一路回車,使用默認(rèn)值即可,由于這個Key也不是用于軍事目的,所以也無需設(shè)置密碼。如果一切順利的話,可以在用戶主目錄里找到.ssh目錄,里面有id_rsaid_rsa.pub兩個文件,這兩個就是SSH Key的秘鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。
  • 第2步:登陸GitHub,在主頁點擊右上角的個人頭像,選擇setting,然后在邊的列表里點擊SSH and GPG keys,再點擊New SSH key。填上任意Title,在Key文本框里粘貼id_rsa.pub文件的內(nèi)容:

添加遠程庫

先在GitHub上新建一個倉庫


GitHub告訴我們,可以從這個倉庫克隆出新的倉庫,也可以把一個已有的本地倉庫與之關(guān)聯(lián),然后,把本地倉庫的內(nèi)容推送到GitHub倉庫。
現(xiàn)在,我們根據(jù)GitHub的提示,在本地的learngit倉庫下運行命令:
$ git remote add origin git@github.com:dragon-mystic/binglan-week1.git
其中orgin是遠程庫的意思,dragon-mystic是自己在GitHub上的賬戶名,binglan-week1是GitHub倉庫名稱。
下面就可以把把本地庫的內(nèi)容推送到遠程,用git push命令,實際上是把當(dāng)前分支master推送到遠程。
由于遠程庫是空的,第一次推送master分支時,加上了-u參數(shù),Git不但會把本地的master分支內(nèi)容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關(guān)聯(lián)起來,在以后的推送或者拉取時就可以簡化命令。

這里出現(xiàn)了一個SSH警告,這是因為Git使用SSH連接,而SSH連接在第一次驗證GitHub服務(wù)器的Key時,需要你確認(rèn)GitHub的Key的指紋信息是否真的來自GitHub的服務(wù)器,輸入yes回車即可。Git會輸出一個警告,告訴你已經(jīng)把GitHub的Key添加到本機的一個信任列表里了。這個警告只會出現(xiàn)一次,后面的操作就不會有任何警告了。
此時刷新網(wǎng)頁可以看到GitHub的倉庫內(nèi)容和本地的一樣了:

從現(xiàn)在起,只要本地作了提交,就可以通過命令:
$ git push origin master
把本地master分支的最新修改推送至GitHub。

從遠程庫克隆

首先先建立一個新的倉庫copy


勾選Initialize this repository with a README,這樣GitHub會自動為我們創(chuàng)建一個README.md文件。創(chuàng)建完畢后,可以看到README.md文件:

現(xiàn)在可以用命令git clone來克隆倉庫:
$ git clone git@github.com:dragon-mystic/copy.git

(這里克隆的是本地庫,后面同樣寫的是自己GitHub的倉庫地址)
copy會存在于本地庫的learngit目錄下,而且可以看到copy目錄下有README.md文件;


分支管理

一開始Git會自動創(chuàng)建一個分支master,Git用master指向最新的提交,再用HEAD指向master,就能確定當(dāng)前分支,以及當(dāng)前分支的提交點。每次提交master會跟著提交不斷延長,指向最新的提交。

創(chuàng)建與合并分支

創(chuàng)建新的分支之后,把HEAD的指向改變到新的分支上,繼續(xù)提交,新的分支就會根據(jù)后來的提交而移動,而原來的master就會停止在HEAD指向改變之前的最后一次的提交。
使用命令git checkout創(chuàng)建新的分支binglan


git checkout命令加上-b參數(shù)表示創(chuàng)建并切換,相當(dāng)于以下兩條命令:

$ git branch binglan
$ git checkout binglan
Switched to branch 'binglan'

git branch命令查看當(dāng)前分支:


*后面就是當(dāng)前分支。然后就可以在分支binglan上提交工作了。如果再想回到分支master上就使用命令git checkout就行了:

如果之前在分支上binglan上做了任何的操作,在回到分支master之后是看不到的。
使用命令git merge可以合并分支(前提是你在分支binglan上進行了修改):

此時分支master上的內(nèi)容就會和分支binglan上的一樣。上面顯示的Fast-foward是快進的意思,由于這次的修改你較小,所以合并速度很快。
合并完成后可以使用命令git branch -d刪除分支:

就只剩下master分支了:

switch

這是一個更科學(xué)的命令,同樣可以用來創(chuàng)建合并分支:
創(chuàng)建并切換到新的binglan分支,可以使用:
$ git switch -c dev
直接切換到已有的master分支,可以使用:
$ git switch master


解決沖突

在兩個分支上分別做一個修改時(master分支和新分支各自都分別有新的提交),Git無法執(zhí)行“快速合并”,只能試圖把各自的修改合并,此時很有可能會發(fā)生沖突,此時Git會提示沖突,使用命令git status同樣可以查看這個沖突。此時需要手動去更改,使用命令git log --graph --pretty=oneline --abbrev-commit可以查看合并情況,最后再刪去新分支。

分支管理策略

在合并時,Git一般會使用Fast-forward的模式,但是在刪除分支之后會丟失這條分支的信息。使用命令git merge --no-ff -m "merge with no-ff" binglan可以強制禁用Fast-forward模式,Git會在merge時產(chǎn)生一個新的commit,這樣就可以在分支歷史上查看分支信息(git log)。
Git創(chuàng)建的master分支是很穩(wěn)定的,而自己創(chuàng)建的新分支是不穩(wěn)定的。所以一般都在自己創(chuàng)建的新分支上進行工作,最后再合并到master上。(在團隊合作的情況下非常實用,一人一條分支,最終合并到一起)

Bug分支

用于臨時修復(fù)Bug創(chuàng)建的一個臨時分支。當(dāng)在用自己創(chuàng)建的分支工作時突然要修復(fù)一個Bug,此時使用命令git stash可以隱藏當(dāng)前工作的分支并保存工作進度,再創(chuàng)建一個臨時分支去修復(fù)Bug。可以使用命令git stash list查看隱藏的分支,在Bug修復(fù)之后,刪去臨時分支,使用命令git stash apply恢復(fù)隱藏的分支,再使用命令git stash drop刪除隱藏分支時stash內(nèi)容(也可以使用命令git stash pop恢復(fù)并刪除)。stash可以重復(fù)使用多次,要恢復(fù)指定的stash,用命令$ git stash apply stash@{0}{}里面就是恢復(fù)的第幾次的stash)。
使用命令cherry-pick ···能復(fù)制一個特定的提交到當(dāng)前分支,···即你想要的`commit·的版本號。

Feature分支

用于開發(fā)新的東西,防止一些實驗性質(zhì)的代碼把主分支搞亂,F(xiàn)eature分支在合并時和Bug分支是一樣的,如果要強行刪除這個Feature分支,則要使用命令git branch -D <name>。

推送分支

當(dāng)從遠程倉庫克隆時,Git自動把本地的master分支和遠程的master分支對應(yīng)起來了,并且,遠程倉庫的默認(rèn)名稱是origin。可以使用命令git remote查看遠程庫的信息,或者,用git remote -v顯示更詳細(xì)的信息:


上面顯示了可以抓取和推送的origin的地址。
推送分支,就是把該分支上的所有本地提交推送到遠程庫。推送時,要指定本地分支,例如:$ git push origin master

  • master分支是主分支,因此要時刻與遠程同步;
  • 自己創(chuàng)建的主分支是開發(fā)分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;
  • bug分支只用于在本地修復(fù)bug,就沒必要推到遠程了。
  • feature分支是否推到遠程,取決于是否和其他人合作在上面開發(fā)。

抓取分支

一般情況下,別人從你的遠程庫clone只能看到你的master分支,但是如果別人想在你自己創(chuàng)建的分支binglan上開發(fā),就必須使用命令$ git checkout -b binglan origin/binglan創(chuàng)建遠程origin的binglan分支到本地。然后他就可以在binglan這個分支上進行修改并push。如果別人和你在這個分支上對相同的文件進行了修改,并且試圖推送,會發(fā)生沖突,此時需要用命令git pull把最新的提交從origin/binglan上抓取下來,然后在本地合并,解決沖突,再推送(在git pull時一定要先設(shè)置binglan和origin/binglan的鏈接: $ git branch --set-upstream-to=origin/binglan binglanpull)。再將合并的沖突進行手動解決,就和分支管理的一樣。解決后再push


結(jié)語

Git的功能真的很強大,可以實現(xiàn)多人協(xié)作開發(fā),能與別人分享自己的經(jīng)驗和作品,有關(guān)Git還要學(xué)的東西還很多。
插上一個Git常用命令總結(jié)(方便快速查找):



未完待續(xù)······

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

友情鏈接更多精彩內(nèi)容