git命令詳細版


使用的時候常忘記,因此記錄一下長點心吧!
注:文檔較長,可以轉到目錄有選擇查閱。
在這裏插入圖片描述
Git 是目前最流行、最好用的版本控制系統,在它的基礎之上催生出了 GitHub 和 GitLab 這兩個當前最流行的代碼託管平臺。本文梳理了一些常用的Git命令。

Git(讀音爲/gɪt/。)是一個開源的分佈式版本控制系統,可以有效、高速地處理從
很小到非常大的項目版本管理。Git 是 Linus Torvalds 爲了幫助管理 Linux 內核
開發而開發的一個開放源碼的版本控制軟件。

git整個工作流的whole picture可以參考下面這張圖片:

image-20190831105613619

圖中的各部分分別表示:

  • 工作區Workspace:就是你在電腦裏能看到的目錄,即你代碼放的那個文件夾。即時性強,對文件的所有更改都會立刻提現在這裏
  • 版本庫:工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫
  • 暫存區 Index/Stage:git add以後,當前對文件的更改會保存到這裏
  • 本地倉庫Repository:git commit以後,當前暫存區裏對文件的更改會提交到本地倉庫
  • 遠程倉庫Remote:遠程倉庫名一般默認叫origin。git push以後,本地倉庫裏優先於遠程倉庫的commit會被push到遠程倉庫
    在這裏插入圖片描述

一些基本概念:

  • SVN是集中式版本控制系統,版本庫是集中放在中央服務器的。
  • Git是分佈式版本控制系統,那麼它就沒有中央服務器的,每個人的電腦就是一個完整的版本庫。
  • origin - 這是 Git 給你克隆的倉庫服務器的默認名字。
  • HEAD - 在 Git 中,它是一個指針,指向當前所在的本地分支的最新一次提交(可將 HEAD 想象爲當前分支的別名)。
$ cat .git/HEAD
ref: refs/heads/master # 當前指向master

在這裏插入圖片描述

1.Quick Start

1. 配置用戶信息

第一步需要配置你的git用戶信息

$ git config --global user.name "yourname"
$ git config --global user.email [email protected]

如果使用了 --global 選項,那麼該命令只需要運行一次,因爲之後無論你在該系統上做任何事情, git 都會使用那些信息。
當你想針對特定項目使用不同的用戶名稱與郵件地址時,可以在那個項目目錄下運 行沒有 --global 選項的命令來配置。
配置爲之後,可以用以下命令查看:

 git config --list

注意:github的提交記錄,需要你本地配置的email被加入到了github設置中才會記錄爲有效提交。

詳情參考:

Setting your commit email address on GitHub
Adding an email address to your GitHub account
Why are my contributions not showing up on my profile?

2. 初始化

把普通目錄改成用git管理的倉庫。目錄下會多了一個.git的目錄,這個目錄是git來跟蹤管理版本的

$ git init

3. 常用命令

下面這幾個命令是最最最常用,最最最基本的git命令,可以先走一遍流程。

git status # 查看目前文件夾git的狀態
git add . # 將本地所有的修改添加到暫存區
# git checkout -- <file> # 放棄對某個文件的修改
git commit -m "your description"
git push -u origin master # the first time with -u
# git push origin <要推送的本地分支名>

4. 查看版本庫的更新過程

可以用log查看版本庫的更新過程:

git log
# 查看各版本號及信息(所有的commit:本地commit + 其他同事的commit)
git log –pretty=oneline
git log --graph --pretty=oneline --abbrev-commit
# --pretty=oneline:一行顯示,只顯示哈希值和提交說明(--online本身也可以作爲單獨的屬性)
# --abbrev-commit:僅顯示SHA-1的前幾個字符,而非所有的40個字符

2. 常用的撤銷或回退操作

人非聖賢孰能無過,在執行了不想執行的git add 或者 git commit 或者 git push操作,我們需要執行相應的撤銷操作。

2.1 git add的撤銷

用命令git reset HEAD 可以把暫存區的修改撤銷掉(unstage),重新放回工作區:

$ git reset HEAD readme.txt
Unstaged changes after reset:
M    readme.txt

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

2.2 直接丟棄在工作區對某個文件做的修改

git reset --hard HEAD # 撤銷工作目錄中所有未提交文件的修改內容
git checkout -- readme.txt  # 撤銷工作目錄中制定的未提交文件的修改內容

意思就是,把readme.txt文件在工作區做的修改全部撤銷,這裏有2種情況

  1. 如果 readme.txt修改後還沒有放到暫存區,使用撤銷修改就回到和版本庫一模一樣的狀態(last commit)。
  2. 另外一種是readme.txt已經放入暫存區了,接着又作了修改,撤銷修改就回到添加暫存區後的狀態。但一旦執行了git commit -m “*”,就不能再使用上面的命令回退。
    如果文件已經提交到了暫存區,可以採取以下兩個步驟放棄修改。
git reset HEAD <file> # to unstage, 撤銷git add 
git checkout -- <file> 

git checkout其實是用版本庫裏的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。所以git checkout – [file] 是一個危險的命令。 你對那個文件做的任何修改都會消失 - 你只是拷貝了另一個文件來覆蓋它。 除非你確實清楚不想要那個文件了,否則不要使用這個命令。

2.3 git commit撤銷(沒有push)

git reset --hard HEAD~1 # git reset --hard HEAD^
# 撤銷之前的提交:
# 因爲你使用了 --hard,所有你的文件將重置到上一次提交時的狀態。
# uncommit for reworking: 去掉"--hard",這個對於非merge的commit有效,對於merge的commit最好刪除merge後重新創建。

git reset --soft HEAD~1 # git reset --soft HEAD^
# 撤銷提交但保留文件和索引:
# 從當前分支移除上一次commit,但是當前文件的修改會保留在你的工作區(working tree),同時暫存區(index)的修改也會保留。
# 此時直接用git commit就可以回到git reset之前的狀態。

git reset HEAD~1 # git reset HEAD^
# 要撤銷提交但保留更改:mixed mode,與soft mode非常像。
# 但是隻把更改保留在工作區(working tree)而非暫存區(index),此時需要先git add然後git commit即可回到git reset之前的狀態。

注意git rest --hard HEAD~1的操作非常危險,本地工作區如果有unstaged的修改就會丟失,所以在使用這個命令前一定要保證本地沒有unstaged files,即git status是空的! 所幸:git reset --keep HEAD~1可以作爲git rest --hard HEAD~1的安全版本。

image-20190831123230822

如果某次commit後發現漏了一個文件,可以使用下面命令把這個文件加上上一次的commit中。

$ git add missing_file
$ git commit --amend --no-edit   # "--no-edit": 不編輯, 直接合併到上一個 commit
$ git log --oneline    # "--oneline": 每個 commit 內容顯示在一行

2.4 git push的撤銷

對於已經push的版本,進行回退

# step 1,本地回退到指定的版本
git reset --hard 版本號

# step 2,將遠程的也回退到指定版本
git push  -f origin dev    

2.5 版本回退

# 回到上一個版本
git reset --hard HEAD^ 
# HEAD指向的版本就是當前版本
# 或者使用 git reset --hard HEAD~ 
# ------------------------------ #
# 如果想回退到100個版本:
git reset –-hard HEAD~100
# 本地回退到指定的版本
git reset --hard 版本號 
# ------------------------------ #
# 查看以往版本號(本地的commit)

git log
# 如果要回到未來的版本可以用這個查看
git reflog

2.6 git強制覆蓋本地代碼(與git遠程倉庫保持一致)

$ git fetch --all
$ git reset --hard origin/master 
$ git pull

3. 遠程操作

Git遠程操作詳解: git pull/git fetch/git push等。

3.1 git pull

$ git pull <遠程主機名> <遠程分支名>:<本地分支名>

比如,要取回origin主機的next分支,與本地的master分支合併,需要寫成下面這樣 -

$ git pull origin next:master

# 相當於:
$ git fetch origin next
$ git merge origin/next

如果遠程分支是與當前分支合併,則冒號後面的部分可以省略。

$ git pull origin next

在某些場合,Git會自動在本地分支與遠程分支之間,建立一種追蹤關係(tracking)。比如,在git clone的時候,所有本地分支默認與遠程主機的同名分支,建立追蹤關係,也就是說,本地的master分支自動”追蹤”origin/master分支。
Git也允許手動建立追蹤關係。

git branch --set-upstream master origin/next 
# 新版本git已經不支持該命令,改爲:
git branch --set-upstream-to=origin/master master

上面命令指定master分支追蹤origin/next分支。
如果當前分支與遠程分支存在追蹤關係,git pull就可以省略遠程分支名。

$ git pull origin

上面命令表示,本地的當前分支自動與對應的origin主機”追蹤分支”(remote-tracking branch)進行合併。
如果當前分支只有一個追蹤分支,連遠程主機名都可以省略。

$ git pull

上面命令表示,當前分支自動與唯一一個追蹤分支進行合併。
如果合併需要採用rebase模式,可以使用–rebase選項。

$ git pull --rebase <遠程主機名> <遠程分支名>:<本地分支名>

如果遠程主機刪除了某個分支,默認情況下,git pull不會在拉取遠程分支的時候,刪除對應的本地分支。這是爲了防止,由於其他人操作了遠程主機,導致git pull不知不覺刪除了本地分支。
但是,你可以改變這個行爲,加上參數 -p 就會在本地刪除遠程已經刪除的分支。

$ git pull -p
# 等同於下面的命令
$ git fetch --prune origin 
$ git fetch -p

3.2 git fetch

$ git fetch <遠程主機名>

默認情況下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

$ git fetch <遠程主機名> <分支名>
比如,取回origin主機的master分支。
$ git fetch origin master

所取回的更新,在本地主機上要用”遠程主機名/分支名”的形式讀取。比如origin主機的master,就要用origin/master讀取。

3.3 git push

$ git push <遠程主機名> <本地分支名>:<遠程分支名>
$ git push origin master

上面命令表示,將本地的master分支推送到origin主機的master分支。如果後者不存在,則會被新建。
如果省略本地分支名,則表示刪除指定的遠程分支,因爲這等同於推送一個空的本地分支到遠程分支。

$ git push origin :master
# 等同於
$ git push origin --delete master

上面命令表示刪除origin主機的master分支。
如果當前分支與遠程分支之間存在追蹤關係,則本地分支和遠程分支都可以省略。

$ git push origin

上面命令表示,將當前分支推送到origin主機的對應分支。
如果當前分支只有一個追蹤分支,那麼主機名都可以省略。

$ git push

如果當前分支與多個主機存在追蹤關係,則可以使用-u選項指定一個默認主機,這樣後面就可以不加任何參數使用git push。

$ git push -u origin master

上面命令將本地的master分支推送到origin主機,同時指定origin爲默認主機,後面就可以不加任何參數使用git push了。

$ git push --force origin 

上面命令使用–force選項,結果導致遠程主機上更新的版本被覆蓋。

4. 分支管理

branch management

A successful Git branching model

Understanding the Git Workflow

4.1 概述

並不是一定要把本地分支往遠程推送:

  • master分支是主分支,因此要時刻與遠程同步;一般來說,代碼庫有且只有一個主分支。Git主分支的名字,默認叫做Master。它是自動建立的,版本庫初始化以後,默認就是在主分支在進行開發。
  • dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;
  • bug分支只用於在本地修復bug,就沒必要推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
  • feature分支是否推到遠程,取決於你是否和你的小夥伴合作在上面開發。
# 查看分支:
$ git branch -a

# 創建本地分支:
$ git branch <分支名>

# 切換本地分支:
$ git checkout <分支名> 

# 創建+切換本地分支:
$ git checkout -b <name> 
# 相當於:git branch <分支名> + git checkout <分支名>  

# 合併某分支到當前分支:
$ git merge <要合併的分支>
# 將本地分支推送到遠程
$ git push origin <要推送的本地分支名>
# 以遠程分支爲基礎,建一個本地分支
$ git checkout -b <本地分支名> origin/<遠程分支名>
# 刪除本地分支:
$ git branch -d <本地分支名>
# 刪除遠程分支。將本地空分支推送到遠程分支,相當於刪除遠程分支
$ git push origin  :<要刪除的遠程分支名>

4.2 git tag

Git 使用的標籤有兩種類型:輕量級的(lightweight)和含附註的(annotated)。輕量級標籤就像是個不會變化的分支,實際上它就是個指向特定提交對象的引用。而含附註標籤(git tag -a ),實際上是存儲在倉庫中的一個獨立對象,它有自身的校驗和信息,包含着標籤的名字,電子郵件地址和日期,以及標籤說明,標籤本身也允許使用 GNU Privacy Guard (GPG) 來簽署或驗證。一般我們都建議使用含附註型的標籤,以便保留相關信息;當然,如果只是臨時性加註標籤,或者不需要旁註額外信息,用輕量級標籤也沒問題。創建一個含附註類型的標籤非常簡單,用git tag -a (annotated 的首字母)指定標籤名字即可。

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

  • 命令git tag -a :用於新建一個標籤,默認爲HEAD,也可以指定一個commit id;
  • 可以用git log --pretty=oneline --abbrev-commit : 找到歷史提交的commit_id
  • 命令git tag -a -m “blablabla…”: -m 選項則指定了對應的標籤說明,Git 會將此說明一同保存在標籤對象中。
  • 命令git tag可以查看所有標籤。
  • 可以使用 git show 命令查看相應標籤的版本信息,並連同顯示打標籤時的提交對象。
git tag # 列出所有標籤
git tag -l 'v1.4.2.*' # 搜索模式
git tag -a v1.4 -m 'my version 1.4' 
git show v1.4

後期加註標籤:

# 後期加註標籤,在提交 “updated rakefile” 後爲此項目打上版本號 v1.2
$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

$ git tag -a v1.2 9fceb02

默認情況下,git push 並不會把標籤傳送到遠端服務器上,只有通過顯式命令才能分享標籤到遠端倉庫。其命令格式如同推送分支,運行 git push origin [tagname] ,比如:

$ git push origin v1.5

如果要一次推送所有本地新增的標簽上去,可以使用 --tags 選項:

$ git push origin --tags

4.3 master和dev分支

git clone 默認會把遠程倉庫整個給clone下來,但只會在本地默認創建一個master分支,可以使用checkout命令來把遠程分支取到本地。

git clone ...
git checkout -b dev origin/dev
# 或者使用-t參數,它默認會在本地建立一個和遠程分支名字一樣的分支
git checkout -t origin/dev

git branch

git branch -r # 查看遠程分支
git branch -a # 查看所有分支
# Git創建Develop分支的命令:
git checkout -b develop master

# 將Develop分支發佈到Master分支的命令:
# 切換到Master分支
git checkout master

# 對Develop分支進行合併
git merge --no-ff develop
# 可能需要進行一下分支的關聯,指定本地dev分支與遠程origin/dev分支的鏈接:
$ git branch --set-upstream-to=origin/dev dev

4.4 Fast-Forward

當前分支合併到另一分支時,如果沒有分歧解決,就會直接移動文件指針。這個過程叫做fast forward
舉例來說,開發一直在master分支進行,但忽然有一個新的想法,於是新建了一個develop的分支,並在其上進行一系列提交,完成時,回到 master分支,此時,master分支在創建develop分支之後並未產生任何新的commit。此時的合併就叫fast forward

About parameter: --no-ff
在這裏插入圖片描述

4.5 臨時性分支

Master和Develop是版本庫的主要分支。前者用於正式發佈,後者用於日常開發。常設分支只需要這兩條就夠了。

但是,除了常設分支以外,還有一些臨時性分支,用於應對一些特定目的的版本開發。臨時性分支主要有三種:

  • 功能(feature)分支
# 功能分支的名字,可以採用feature-*的形式命名。
# 創建一個功能分支:
git checkout -b feature-x develop
# 開發完成後,將功能分支合併到develop分支:
git checkout develop
git merge --no-ff feature-x
# 刪除feature分支:
git branch -d feature-x
  • 預發佈(release)分支
# 創建一個預發佈分支:
git checkout -b release-1.2 develop
# 確認沒有問題後,合併到master分支:
git checkout maste
git merge --no-ff release-1.2
# 對合並生成的新節點,做一個標籤
git tag -a 1.2
# 再合併到develop分支:
git checkout develop
git merge --no-ff release-1.2
# 最後,刪除預發佈分支:
git branch -d release-1.2
  • 修補bug(fixbug)分支
# 創建一個修補bug分支:
git checkout -b fixbug-0.1 master
# 修補結束後,合併到master分支:
git checkout master
git merge --no-ff fixbug-0.1
git tag -a 0.1.1
# 再合併到develop分支:
git checkout develop
git merge --no-ff fixbug-0.1
# 最後,刪除"修補bug分支":
git branch -d fixbug-0.1

4.6 git stash

具體操作時,可能會用到 git stash

1、儲藏更改:將當前更改的代碼儲藏起來,等以後恢復使用

git stash

2、恢復儲藏的代碼

git stash pop 
//恢復的同時把stash內容刪掉

或者

git stash apply  
//恢復stash,但是stash內容並不刪除
git stash drop 
//在上面操作的基礎上,以此來刪除stash

注: git stash list : 查看全部的stash列表。

3、將stash空間清空

git stash clear

4、git stash popgit stash apply 區別

原來git stash pop stash@{id}命令會在執行後將對應的stash idstash list裏刪除,而 git stash apply stash@{id} 命令則會繼續保存stash id

4.7 Example

git checkout -b newbranch # create a new branch
# do something...
git add .
git commit -m "do sth"
git checkout master
git merge --no-ff -m "merge new branch" newbranch # merge with no fast forward 
git branch -d newbranch
git branch
git push origin master
git push origin dev

# 將本地分支branch1推到遠端的branch2:
git push origin branch1:branch2

# 刪除分支
git branch -D issues1234  //本地強制刪除分支issues1234    
git push origin  :issues1234  //推到遠程
master分支是主分支,因此要時刻與遠程同步。
#一些修復bug分支不需要推送到遠程去,
#可以先合併到主分支上,然後把主分支master推送到遠程去。
#把遠程的origin的dev分支到本地來,可使用命令創建本地dev分支:
git checkout  –b dev origin/dev

5. Conflicts

發生衝突的文件

<<<<<<< HEAD

Creating a new branch is quick & simple.

=======

Creating a new branch is quick AND simple.

>>>>>>> feature1

其中,git使用 <<<<<<<, =======, >>>>>>> 標記文件中自己和別人產生衝突的部分。

<<<<<<<, ======= 之間爲自己的代碼,先出現;

=======, >>>>>>> 之間爲別人的代碼,後出現。

查看遠程庫信息,使用`git remote -v`;
修改遠程倉庫地址`git remote set-url origin new_git_url`
本地新建的分支如果不推送到遠程,對其他人就是不可見的;
從本地推送分支,使用git push origin branch-name,如果推送失敗,先用git pull抓取遠程的新提交;
在本地創建和遠程分支對應的分支,使用`git checkout -b branch-name origin/branch-name`,本地和遠程分支的名稱最好一致;
建立本地分支和遠程分支的關聯,使用`git branch --set-upstream branch-name origin/branch-name`;
從遠程抓取分支,使用`git pull`,如果有衝突,要先處理衝突。

6. diff

要查看尚未暫存的文件更新了哪些部分,不加參數直接輸入git diff

$ git diff

此命令比較的是工作目錄中當前文件和暫存區域快照之間的差異, 也就是修改之後還沒有暫存起來的變化內容。
如果暫存了,用git diff就沒有反應了。
若要查看已暫存的將要添加到下次提交裏的內容,可以用 git diff --cached 命令。(Git 1.6.1 及更高版本還允許使用 git diff --staged,效果是相同的,但更好記些。)

總結:

git diff # shows unstaged changes.
git diff --cached # shows staged changes.
git diff HEAD # shows all changes (both staged and unstaged).
版本之間的差異
# 上次提交:HEAD^
git diff HEAD^ HEAD

# As of Git 1.8.5, @ is an alias for HEAD, so you can use:
git diff @~..@

#The following will also work:
git show

# If you want to know the diff between head and any commit you can use:
git diff commit_id HEAD

# And this will launch your visual diff tool (if configured):
git difftool HEAD^ HEAD

# Since comparison to HEAD is default you can omit it (as pointed out by Orient):

git diff @^
git diff HEAD^
git diff commit_id

7. submodule

https://www.cnblogs.com/nicksheng/p/6201711.html

https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97

REFERENCE

git cheat sheet

GitHub 漫遊指南 – GitHub 漫遊指南

git - 簡明指南

廖雪峯git

GIT tutorial

GIT PRO BOOK (Chinese)

git tutorial

how to teach git

Follow these simple rules and you’ll become a Git and GitHub master

Git重要概念與常用命令(中文版,速查)

Implementing Git in Data Science

https://www.runoob.com/git/git-basic-operations.html
https://www.w3cschool.cn/git/git-cheat-sheet.html
https://git-scm.com/book/zh/v2

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