關注微信公共號:小程在線
關注CSDN博客:程志偉的博客
Git是世界上最先進的分佈式版本控制系統,克隆一個項目的速度非常快
每個開發都可以從master上克隆一個本地版本庫,就算沒有網絡,也可以提交代碼到本地倉庫、查看log、創建項目分支等等
每個版本庫都可以創建無限個分支,分支是個完整的目錄,且這個目錄擁有完整的實際文件
一、安裝
網上搜一下安裝教程,這裏就不介紹了
安裝完成後,在開始菜單裏找到“Git”->“Git Bash”,彈一個類似命令行窗口的東西,就說明Git安裝成功
接着需要設置一下機器信息,這臺機器上的所有Git倉庫都會使用這個配置
$ git config --global user.name "username"
$ git config --global user.email "[email protected]"
二、創建版本庫
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 -> master)
Author: hxk <[email protected]>
Date: Fri July 20 21:06:15 2018 +0800
append ABC
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: hxk <[email protected]>
Date: Fri July 20 20:59:18 2018 +0800
a new file
git log顯示最近到最遠的提交日誌,我們可以看到兩次提交,最後一次是append ABC
git的版本號是用SHA1計算出來的一個16進制數
如果嫌輸出信息太多,可以加上--pretty=oneline
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> 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 <[email protected]>
Date: Fri July 20 20:59:18 2018 +0800
a new file
之前那個版本已經看不到了,這時如果想回到之前那個版本,需要知道版本號,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 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")
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
提交後沒有對工作區進行修改的話,查看狀態,工作區是乾淨的
$ 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 <file>:
$ 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 <file>和git add<file>效果是一樣的。
六、分支管理
1、創建與合併分支
每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向master,master纔是指向提交的,所以,HEAD指向的就是當前分支。
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:
每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也越來越長。
當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
你看,Git創建一個分支很快,因爲除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!
不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指針往前移動一步,而master指針不變:
假如我們在dev上的工作完成了,就可以把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
所以Git合併分支也很快!就改改指針,工作區內容也不變!
合併完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,我們就剩下了一條master分支:
------------------------------------測試開始---------------------------------------------------
1)創建分支 git branch <name>
切換分支 git checkout <name>
首先,我們創建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分支此刻的提交點並沒有變:
3)合併某個分支到當前分支 git merge <name>
現在,我們把dev分支的工作成果合併到master分支上:
$ git merge dev
git merge命令用於合併指定分支到當前分支。合併後,再查看test.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。
4)刪除分支 git branch -d <name>
合併完成後,就可以放心地刪除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 & Simple
當兩個分支都分別有了新的提交,如下圖所示:
這種情況下無法進行快速合併,只能試圖把各自的修改合併起來,這樣有可能會造成衝突:
$ 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")
查看test.txt文件的內容:
Hello World ABC
<<<<<<< HEAD
This is the second line & Simple
=======
This is the second line AND Simple
>>>>>>> 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 log --graph --pretty=oneline --abbrev-commit可以看到分支的合併情況,包括分支合併圖(--graph)、一行顯示(--pretty=oneline)、提交校驗碼縮略(--abbrev-commit)顯示:
$ git log --graph --pretty=oneline --abbrev-commit
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & 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後就像這樣:如下圖所示:
分支策略
master分支是最穩定的,只能用於發佈新版本,平時不能在上面進行開發,要在新建的分支上進行開發,比如dev,這時dev是不穩定的,到產品1.0發佈時,將dev分支和master分支合併,在master分支上發佈1.0版本。
所以團隊合作的分支看起來就像這張圖一樣:
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-->
rebase-->
七、標籤管理
切換到需要打標籤的分支上
1)新建一個標籤(默認爲HEAD,也可以指定一個commit id)
創建帶有說明的標籤,用-a指定標籤名,-m指定說明文字
$ git tag <標籤名>
$ git tag <標籤名> <commit id>
$ git tag -a <標籤名> -m "備註"
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 <tagname>
推送全部尚未推送到遠程的本地標籤 git push origin --tags
$ git push origin <標籤名>
$ git push origin --tags
以上。
————————————————
版權聲明:本文爲CSDN博主「最近比較煩。」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_34964197/article/details/81104419