Git教程傳送門 -> https://www.liaoxuefeng.com/wiki/896043488029600/896067074338496
1.Git簡介
Git是目前世界上最先進的分佈式版本控制系統
分支管理
集中式版本控制系統需要聯網工作,局域網帶寬夠還好,如果遇到互聯網網速慢的情況提交慢。
eg:CVS、SVN、ClearCase
分佈式版本控制系統沒有“中央服務器”,每個人電腦上都有一個完整的版本庫,安全不易丟失數據
分佈式版本控制系統通常也有一臺充當“中央服務器”的電腦,但這個服務器的作用僅僅是用來方便“交換”大家的修改,沒有它大家也一樣幹活,只是交換修改不方便而已。
eg:Git、BitKeeper、Mercurial、Bazaar
1.1 安裝Git
Linux環境安裝Git
Debian/Ubuntu => sudo apt-get install git
其它Linux版本 => 通過源碼安裝(Git官網下載源碼 -> 解壓 -> 依次輸入: ./config, make, sudo make install)
安裝完成後,還需要最後一步設置,在命令行輸入:
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
因爲Git是分佈式版本控制系統,所以,每個機器都必須自報家門:你的名字和Email地址。
注意: git config命令用了--global參數,表示你這臺機器上所有的Git倉庫都會使用這個配置。
1.2 創建版本庫
版本庫又名倉庫(repository),可以簡單理解成一個目錄,這個目錄裏面的所有文件都可以被Git管理起來,每個文件的創建、修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。
說明:所有的版本控制系統,其實只能跟蹤文本文件的改動,比如TXT文件,網頁,所有的程序代碼等等,Git也不例外。如果要真正使用版本控制系統,就要以純文本方式編寫文件。
圖片、視頻、Word格式文檔是二進制文件,雖然也能由版本控制系統管理,但沒法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是隻知道圖片從100KB改成了120KB,修改了什麼內容版本控制系統不知道。
@創建版本庫
1.選擇一個合適的地方,創建一個空目錄:
$ mkdir learngit
2.初始化Git倉庫:
$ cd learngit
$ git init
說明:當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,不要手動修改這個目錄裏面的文件。
@添加文件到Git倉庫
使用命令git add <file>,注意,可反覆多次使用,添加多個文件;
使用命令git commit -m <message>,完成。
2.時光穿梭機
@git status命令和git diff命令
使用git status命令隨時掌握工作區的狀態。
使用git diff可以查看修改內容。
2.1 版本回退
HEAD指向的版本就是當前版本,上一個版本就是HEAD^,上上一個版本就是HEAD^^,往上100個版本可以寫成HEAD~100。
因此,Git允許我們在版本的歷史之間穿梭,
@git reset命令
使用git reset --hard HEAD^ 回退到上一個版本
使用git reset --hard <commit_id> 回退到指定版本(版本號寫前幾位就行)
@git log命令
穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。
@git reflog命令
要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。
2.2 工作區和暫存區 & 2.3管理修改
工作區(Working Directory)
就是你在電腦裏能看到的目錄,比如我的learngit文件夾就是一個工作區。
版本庫(Repository)
工作區有一個隱藏目錄.git,這個不算工作區,是Git的版本庫。
Git的版本庫裏存了很多東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。
把文件往Git版本庫裏添加分兩步執行:
git add添加文件 => 把文件修改添加到暫存區(工作區 -> 暫存區);
git commit提交更改 => 把暫存區的所有內容提交到當前分支(暫存區 -> master分支)。
2.4 撤銷修改
@丟棄工作區修改
場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file。
這個命令會用版本庫裏的版本替換工作區的版本。
@丟棄暫存區修改
場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步:
第一步用命令git reset HEAD <file>,就回到了場景1,第二步按場景1操作。
@分支回退
場景3:已經提交了不合適的修改到版本庫時(未推送到遠程庫),想要撤銷本次提交,用命令 git reset --hard HEAD^。
2.5 刪除文件
@git rm命令
工作區刪除文件 rm test.txt => 如果是手誤,使用 git checkout -- test.txt 恢復
將修改添加到暫存區 git add test.txt 或者使用 git rm test.txt
提交至分支 git commit -m "test.txt"
3.遠程倉庫
前提:登錄Github,添加SSH Key
3.1 添加遠程庫
場景:已在本地創建了一個Git倉庫後,又想在GitHub創建一個Git倉庫,並且讓這兩個倉庫進行遠程同步。這樣,GitHub上的倉庫既可以作爲備份,又可以讓其他人通過該倉庫來協作
step1 Github上創建新倉庫
首先,登陸GitHub,然後,在右上角找到“Create a new repo”按鈕,創建一個新的倉庫;
在Repository name填入learngit,其他保持默認設置,點擊“Create repository”按鈕,就成功地創建了一個新的Git倉庫(此時,在GitHub上的這個learngit倉庫還是空的)
step2 本地倉庫與Github上的倉庫關聯
@關聯遠程倉庫
在本地的learngit倉庫,使用命令 git remote add origin git@server-name:path/repo-name.git,例如
$ git remote add origin [email protected]:<GitHub賬戶名>/learngit.git
添加後,遠程庫的名字就是origin,這是Git默認的叫法,也可以改成別的,但是origin這個名字一看就知道是遠程庫。
@第一次推送master分支的所有內容
$ git push -u origin master
加上參數-u,會把本地的master分支和遠程的master分支關聯起來,在以後的推送或者拉取時就可以簡化命令。
@(非首次)提交推送最新修改
$ git push origin master
把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。
3.2 從遠程庫克隆
準備好一個遠程庫,例如gitskills.git
@git clone克隆倉庫
本地文件路徑執行如下命令
$ git clone [email protected]:<GitHub賬戶名>/gitskills.git
Git支持多種協議,默認的git://使用ssh,但也可以使用https等其他協議。
4 分支管理
4.1 創建與合併分支
HEAD指向主分支/master分支,master指向提交。每次提交,master分支都會向前移動一步。
創建分支 => 創建新指針dev,HEAD改爲指向這個新指針
合併分支 => 把master指向dev的當前提交
刪除分支 => 刪除指針dev
@創建、切換到新分支
創建dev分支,然後切換到dev分支:
$ git checkout -b dev
-b參數表示創建並切換,相當於以下兩條命令:
$ git branch dev
$ git checkout dev
或者用如下新命令
$ git switch -c dev
@查看當前分支
$ git branch
* dev
master
git branch命令會列出所有分支,當前分支前面會標一個*號。
@切換分支
切換到master
$ git checkout master
或者用如下新命令
$ git switch master
@合併分支
合併dev的改動至master
$ git merge dev
git merge命令用於合併指定分支到當前分支。
@刪除分支
刪除dev分支
$ git branch -d dev
4.2 解決衝突
場景:兩個分支分叉,不在一條線,且指向的提交內容有衝突
當Git無法自動合併分支時,就必須首先解決衝突。
解決衝突就是把Git合併失敗的文件手動編輯爲我們希望的內容,再提交。
@用git log --graph命令查看分支合併圖
$ git log --graph --pretty=oneline --abbrev-commit
4.3 分支管理策略
通常合併分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。
合併分支時,加上--no-ff參數禁用Fast forward,合併後的歷史有分支,能看出來曾經做過合併,而fast forward合併就看不出來曾經做過合併。
@普通模式合併分支
$ git merge --no-ff -m "merge with no-ff" dev
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活。
幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;
你和你的小夥伴們每個人都有自己的分支,時不時地往dev分支上合併就可以了。
4.4 Bug分支
- 修復bug時,我們會通過創建新的bug分支進行修復,然後合併,最後刪除;
- 當手頭工作沒有完成時,先把工作現場git stash一下,然後去修復bug,修復後,再git stash pop,回到工作現場;
- 在master分支上修復的bug,想要合併到當前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“複製”到當前分支,避免重複勞動。
@保存工作現場、去修復Bug
$ git stash
去master創建分支issue-101並修復Bug
首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master創建臨時分支
$ git checkout master
$ git checkout -b issue-101
…
$ git commit -m "fix bug 101"
[issue-101 4c805e2] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch master
$ git merge --no-ff -m "merged bug fix 101" issue-101
@返回工作現場
$ git switch dev
$ git status
On branch dev
nothing to commit, working tree clean
工作區是乾淨的,用git stash list命令看看
$ git stash list
stash@{0}: WIP on dev: f52c633 add merge
工作現場還在,Git把stash內容存在某個地方了,需要恢復
@恢復工作現場的兩種方法
1)git stash apply 恢復後stash內容並不刪除,你需要用git stash drop來刪除;
$ git stash apply stash@{0}
2)git stash pop 恢復的同時把stash內容也刪除
@將Bug修復合併到其它有Bug的分支
Git提供了一個cherry-pick命令,讓我們能複製一個特定的提交到當前分支:
$ git branch
* dev
master
$ git cherry-pick 4c805e2
[master 1d4b803] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)
4.6 Feature分支
開發一個新feature,最好新建一個分支;
如果要丟棄一個沒有被合併過的分支,可以通過git branch -D <name>強行刪除。
4.7 多人協作
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,並且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,用git remote:
$ git remote
origin
用git remote -v顯示更詳細的信息(顯示了可以抓取和推送的origin的地址):
$ git remote -v
origin [email protected]:michaelliao/learngit.git (fetch)
origin [email protected]:michaelliao/learngit.git (push)
@推送分支
把該分支上的所有本地提交推送到遠程庫。推送時要指定本地分支。
$ git push origin master
@抓取分支
多人協作時,大家都會往master和dev分支上推送各自的修改。工作模式通常是這樣:
首先,可以試圖用git push origin <branch-name>推送自己的修改;
如果推送失敗,則因爲遠程分支比你的本地更新,需要先用git pull試圖合併;
如果合併有衝突,則解決衝突,並在本地提交;
沒有衝突或者解決掉衝突後,再用git push origin <branch-name>推送就能成功!
如果git pull提示no tracking information,則說明本地分支和遠程分支的鏈接關係沒有創建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
4.8 Rebase
rebase操作可以把本地未push的分叉提交歷史整理成直線;
rebase的目的是使得我們在查看歷史提交的變化時更容易,因爲分叉的提交需要三方對比。
$ git rebase
5 標籤管理
5.1 創建標籤
@打標籤
首先切換到需要打標籤的分支上
1) git tag <name>可以打一個新標籤,默認標籤是打在最新提交的commit上的
$ git tag v1.0
2) git tag <tagname> <commit id>可以給歷史提交打標籤
3) 創建帶有說明的標籤,用-a指定標籤名,-m指定說明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
注意:標籤總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那麼在這兩個分支上都可以看到這個標籤。
@查看標籤
git tag 查看所有標籤
git show <tagname> 查看標籤信息
5.2 刪除標籤
git push origin <tagname> 推送一個本地標籤
git push origin --tags 推送全部未推送過的本地標籤
git tag -d <tagname> 刪除一個本地標籤
git push origin :refs/tags/<tagname> 刪除一個遠程標籤