Git詳解

前言

Git是目前世界上最先進的分佈式版本控制系統。本文從頭詳細地介紹了Git的各種用法。

配置本機用戶和郵箱

λ git config --global user.name 名字
λ git config --global user.email 郵箱 

注意:git config--global參數代表本機上所有git倉庫都用這個配置。
若想爲某個倉庫配置其它的用戶名和郵箱:

λ git config -user.name 名字
λ git config ser.email 郵箱 

查看全局用戶名和郵箱:

λ git config --global user.name
λ git config --global user.email

查看某倉庫用戶名和郵箱同理,上述語句去掉--global就可以。

創建倉庫

將當前目錄編程Git可以管理的倉庫:

λ git init
Initialized empty Git repository in C:/Users/hwx/Desktop/learngit/.git/

C:/Users/hwx/Desktop/learngit是我的目錄,.git目錄用來跟蹤管理版本庫,不用管它。

將文件添加到版本庫

注意:所有版本控制系統只能跟蹤文本文件的改動,可以告訴你每次改動的細節。但是不能跟蹤圖片、視頻這些二進制文件的變化,只能知道文件大小的變化。

下面我們添加一個readme.txt到倉庫,分兩步:

1.用命令git add將文件添加到暫存區:

λ git add readme.txt

該命令執行成功不會有任何顯示,可以同時add多個文件,中間用空格隔開。

2.用命令git commit將文件從暫存區提交到倉庫:

λ git commit -m "add a readme text"
[master (root-commit) 6fd4dfc] add a readme text
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

-m後面是本次提交的說明。
注意:git commit只會提交暫存區中的修改,沒放進暫存區的不會提交。

git status

查看倉庫狀態。

1.倉庫中有文件沒add

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

        .1.txt.swp

nothing added to commit but untracked files present (use "git add" to track)

2.倉庫中有文件修改過了,但是沒add

λ 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:   readme.txt

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

3.倉庫中有文件add了,但是沒有commit

λ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

4.倉庫該add的都add了,該commit的都commit了

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

git diff

工作區是目錄,倉庫是版本庫。
git diff 比較的是工作區文件與暫存區文件(上次git add 的內容)的區別
git diff --cached比較的是暫存區的文件與倉庫文件(上次git commit 的內容)的區別
git diff HEAD -- 比較的是工作區文件和倉庫文件

git log

查看倉庫歷史:

λ git log                                                       
commit e1f285812d2202a32fed025f309fb6e7a68fde49 (HEAD -> master)
Author: Wenxing Hu <[email protected]>                            
Date:   Sat Dec 22 14:22:32 2018 +0800                          
                                                                
    readme add forth line                                       
                                                                
commit 859c43221f414215c34c95004ab3930c407caee6                 
Author: Wenxing Hu <[email protected]>                            
Date:   Sat Dec 22 14:14:04 2018 +0800                          
                                                                
    readme add 3 line                                           
                                                                
commit 6fd4dfc32c1ba2bec1fe5e61b85b721c5ed62d2c                 
Author: Wenxing Hu <[email protected]>                            
Date:   Sat Dec 22 13:57:17 2018 +0800                          
                                                                
    add a readme text                                           

從下到上是按照時間排序的每次commit的信息。

信息太多了?加上--pretty=oneline參數:

λ git log --pretty=oneline
e1f285812d2202a32fed025f309fb6e7a68fde49 (HEAD -> master) readme add forth line
859c43221f414215c34c95004ab3930c407caee6 readme add 3 line
6fd4dfc32c1ba2bec1fe5e61b85b721c5ed62d2c add a readme text

每行前面的一大串是commit id。git log --oneline可以只顯示前7位id。

git reset

回退到某一個版本
HEAD是個指針,代表當前的版本。上個版本是HEAD^,上上個是HEAD^^,往上n個版本可以寫成HEAD~n

λ git reset --hard HEAD~
HEAD is now at 859c432 readme add 3 line

注意:執行git reset --hard HEAD^可能會出來個more?這是因爲命令行中^是換行符,所以還是用HEAD~1吧。

也可以根據commit id來進行版本變換:

git reset --hard e1f2
HEAD is now at e1f2858 readme add forth line

這裏commit id輸入四個字符就可以了。

注意:git log只能看到HEAD指向的版本及之前的版本。
版本變換多了,弄暈了,不要緊,命令git log --reflog用來查看所有版本。還有命令git reflog可以查看每次執行的命令。

撤銷修改

1.工作區的文件弄壞了,git checkout -- 文件名這條命令可以使它回到最新的add或commit時的狀態,俗稱一鍵還原。
2.工作區的文件弄壞了,還add到了暫存區,用命令git reset HEAD 文件名,可以將其方會工作區,這樣就回到了1的情況,再執行1就可以了。

刪除文件

git rm 文件名,再git commit

λ git rm test.txt
rm 'test.txt'

λ git commit -m "delete test.txt"
[master ee28494] delete test.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 test.txt

遠程倉庫

遠程倉庫這裏以GayHub爲例,當然你也可以自己搭建一個服務器運行Git。
1.將本地倉庫和遠程倉庫通過SSH連接。

λ ssh-keygen -t rsa -C "你的郵箱"
然後根據提示一路回車。。。

運行成功後,可以在用戶主目錄裏找到.ssh目錄,裏面有id_rsaid_rsa.pub兩個文件,這兩個就是SSHKey的祕鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。
然後在GitHub中添加SSH key,把公鑰添加進去就ok了。

2.關聯本地倉庫和遠程倉庫
首先在GitHub中新建一個倉庫(Repository):

按它的提示,在本地倉庫執行命令:

git remote add [email protected]:649453932/git-test.git

將本地倉庫推送到遠程倉庫的命令:

git push -u origin master

其中-u只在第一次推送時加,origin代表遠程倉庫,注意本地倉庫只有commit了的文件纔會推送到遠程倉庫。

之後每次推送時**git push origin 分支名**,你可以推送本地的mastet到遠程倉庫,當然也可以選擇本地的其他分支推送。注意:遠程倉庫也可以有好多分支。

移除關聯的遠程倉庫:

git remote rm origin

3.從遠程倉庫克隆

git clone [email protected]:649453932/git-test.git

可以隨便從GitHub中clone倉庫,clone回來就成了你的一個本地庫,但保留了該倉庫之前的各種記錄。

分支管理

剛開始,只有一個分支,名爲master,可以再創建分支,分支之間平時互不影響,可以並行開發。
查看所有分支:git branch,當前分支前會有個*
創建分支:git branch 名字
切換到分支:git checkout 名字
創建並切換到分支:git checkout -b 名字
合併指定分支到當前分支:git merge 名字
刪除分支:git branch -d 名字

衝突處理

若master分支和另外一個分支同時對一個文件做了修改,那就不能merge了。
這就需要我們手動解決了:

λ cat readme.txt      
This is a readme text.
This is second line.  
This is third line.   
forth                 
fifth                 
sixth                 
seventh               
eighth_master_dev1    
<<<<<<< HEAD          
master !!!            
=======               
dev2 !!!              
>>>>>>> dev2          

Git用<<<<<<<=======>>>>>>>標記出不同分支的內容我們把這些符號刪掉,改成我們想要的內容。再在master分支上add和commit,主分支就改好了,另外一個分支現在就可以merge了。

圖形化分支合併情況

git log --graph命令可以查看分支合併情況:

λ git log --graph --pretty=oneline --abbrev-commit
*   99fdeac (HEAD -> dev2, master) conflict fixed!
|\
| * 47c854e ADD eighth
* | 53ba977 ADD eighth_maser
|/
* e555cd8 branch test
* ee28494 (origin/master) delete test.txt
* 0ec907e add test.txt
* cd95b35 fidth line
* 6fd4dfc add a readme text

分支merge技巧

通常,合併分支merge時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。
使用--no-ff可以禁用Fast forward,merge時會生成新的commit,就可以從log看到分支。
git merge --no-ff -m "merge with no-ff" 要merge的分支名

λ git merge --no-ff -m "merge noff" dev7
Merge made by the 'recursive' strategy.
 readme.txt | 1 +
 1 file changed, 1 insertion(+)

然後我們看log,dev6是 Fast forwar 模式進行merge的,而dev7是--no-ff模式進行merge的:

λ git log --graph --pretty=oneline --abbrev-commit
*   5571146 (HEAD -> master) merge noff
|\
| * dbc506e (dev7) dev7
|/
* 2122b61 (dev6) dev6
|
...

git stash

該命令可以將工作現場存儲起來,之後可以再恢復。用於臨時處理其它分支的事務,處理完再回來將自己存儲的工作現場恢復。

λ git stash
Saved working directory and index state WIP on dev6: 2122b61 dev6

git stash可以查看存儲的工作現場。
git stash apply恢復現場,但是之後還需要用git stash drop來刪除存儲的。可以直接用git stash pop來恢復現場並刪除存儲。

注意:只有被add過的文件纔會被git stash存儲,注意是add ,只要曾經add過就行。

刪除分支

git branch -d dev1

λ git branch -d dev1
error: The branch 'dev1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev1'.

若該分支沒有被合併,刪除就會丟失該分支上的修改,強制刪除命令:git branch -D 分支名

多人協作

git remote -v:顯示詳細信息

λ git remote -v
origin  [email protected]:649453932/learngit.git (fetch)
origin  [email protected]:649453932/learngit.git (push)

上面顯示了可以抓取和推送的origin的地址。如果沒有推送權限,就看不到push的地址。

從本地推送時用下面的命令,將本地分支推送到遠程倉庫的分支:

git push origin 分支名

若兩個人同時處理一個遠程分支,一個人推送了,另外一個人再推送就會失敗,得先用git pull將最新的提交從origin/分支名抓下來與本地合併,再推送。
也有可能兩人修改了同一個文件,pull下來有衝突,需要手動解決,解決方式見前面的衝突處理

忽略特殊文件

建一個.gitignore文件。
裏面這樣寫:

# 這是註釋
這裏是你想忽略的文件
*可以代指任何字符串
...

這樣每次git status就不會提示這些文件了。

References:

Git教程——廖雪峯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章