Git基礎教程

weixin_33670713發表於2018-05-29

簡介

  • Git是一個開源的分散式版本控制系統,用於敏捷高效地處理任何或小或大的專案。
  • Git 與常用的版本控制工具 CVS, SVN 等不同,它採用了分散式版本庫的方式,不必伺服器端軟體支援。

SVN 區別點

  • GIT是分散式的,SVN不是,這是GIT和其它非分散式的版本控制系統,例如SVN,CVS等,最核心的區別。
  • GIT把內容按後設資料方式儲存,而SVN是按檔案:所有的資源控制系統都是把檔案的元資訊隱藏在一個類似.svn,.cvs等的資料夾裡。即GIT管理的是修改,而SVN管理的是檔案。
  • GIT分支和SVN的分支不同:分支在SVN中一點不特別,就是版本庫中的另外的一個目錄。
  • GIT沒有一個全域性的版本號,而SVN有:目前為止這是跟SVN相比GIT缺少的最大的一個特徵。
  • GIT的內容完整性要優於SVN:GIT的內容儲存使用的是SHA-1雜湊演算法。這能確保程式碼內容的完整性,確保在遇到磁碟故障和網路問題時降低對版本庫的破壞。

配置

Git 提供了一個叫做 git config 的工具,專門用來配置或讀取相應的工作環境變數。

三種不同級別的配置

  • git config --system
        系統使用者級別所擁有的倉庫配置值,基本不用到
  • git config --global
        全域性的倉庫配置值,會去讀寫每個使用者下的~/.gitconfig檔案
  • git config --local
        區域性的倉庫配置值,會去讀寫某個專案下的.git/config檔案

設定使用者資訊

    設定使用者名稱和郵箱,配置的使用者名稱和郵件地址將在版本庫提交時作為提交者的使用者名稱和郵件地址。

git config --global user.name "hyn"
git config --global user.email "example@qq.com"

    如果用 --global選項,那麼更改的配置檔案就是位於你使用者主目錄下的那個配置,以後你所有的專案都會預設使用這裡配置的使用者資訊。
    如果要在某個特定的專案中使用其他名字或者郵箱,只要在對應的專案目錄下去掉--global選項重新配置或者在對應的專案目錄下把--global 換成--local即可,新的設定儲存在當前專案的 .git/config 檔案裡。

設定別名

    可通過alias去修改git命令的別名

  • git status 是用來檢視檔案修改的命令,可以用git st 代替
  • git pull 是用來拉取遠端倉庫程式碼的命令,可以用git pl 代替
  • git push 是用來將本地修改推送到遠端倉庫的命令,可以用git ps 代替
git config --global alias.st status
git config --global alias.pl pull
git config --global alias.ps push

檢視配置資訊

    檢視整個配置資訊:git config --local --list

core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
user.name=hyn
user.email=example@163.com
alias.ps=push

    查詢某個變數的設定:git config --local user.name

hyn

工作區、暫存區和版本庫

基本概念

  • 工作區:你電腦裡專案的目錄。

  • 暫存區:英文叫stage,一般存放在”git目錄”下的index檔案(.git/index)中,所以我們把暫存區有時也叫作索引(index)。

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


    8544948-67483d2a9894fdfa.png
    工作區、暫存區和版本庫之間的關係.png
  • 圖中左側為工作區,右側為版本庫。在版本庫中標記為 stage的區域是暫存區,標記為master的是專案的master分支。

  • 圖中我們可以看出此時HEAD實際是指向 master 分支的一個遊標。所以圖示的命令中出現 HEAD 的地方可以用 master 來替換。

  • 當對工作區修改的檔案執行git add命令時,暫存區的目錄樹被更新即把工作區的修改新增到暫存區;當執行提交操作git commit時,暫存區的目錄樹寫到版本庫中,master 分支會做相應的更新。即把暫存區的內容提交到當前分支

  • 當執行git reset HEAD命令時,暫存區的目錄樹會被重寫,被 master 分支指向的目錄樹所替換,但是工作區不受影響。

  • 當執行 git rm --cached <file>命令時,會直接從暫存區刪除檔案,工作區則不做出改變。

  • 當執行git checkout .或者git checkout -- <file>命令時,會用暫存區全部或指定的檔案替換工作區的檔案。這個操作很危險,會清除工作區中未新增到暫存區的改動。

  • 當執行git checkout HEAD .或者git checkout HEAD <file>命令時,會用 HEAD 指向的 master 分支中的全部或者部分檔案替換暫存區和以及工作區中的檔案。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改動。

版本庫

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

新建本地倉庫

    使用 git init 命令來初始化一個 Git 倉庫, 在執行完成 git init 命令後,Git 倉庫會生成一個 .git 目錄,該目錄包含了資源的所有後設資料,其他的專案目錄保持不變。

  • 使用當前目錄作為倉庫: git init
  • 使用執行目錄作為倉庫: git init 目錄地址

複製遠端倉庫

    使用 git clone從現有的遠端倉庫中拷貝專案

  • 當前目錄下拷貝: git clone 倉庫地址
  • 拷貝到指定目錄: git clone 倉庫地址 目錄地址

基本操作

git init

    建立一個空的Git儲存庫或重新初始化一個現有的儲存庫。

  • 摘要
git init [-q | --quiet] [--bare] [--template=<template_directory>]
      [--separate-git-dir <git dir>]
      [--shared[=<permissions>]] [directory]
  • 描述
        此命令建立一個空的Git儲存庫,會在當前目錄下生成一個.git目錄,該目錄下包含objects, refs/heads, refs/tags和模版檔案。該命令還建立了一個master分支,以及指向master的一個指標叫HEAD。
  • 示例
$ mkdir demo
$ cd demo
$ git init 

Initialized empty Git repository in /Users/huangyangneng/Documents/workspace/git/demo/.git/

在demo目錄下建立了一個空的git倉庫

$ ls -a 
.    ..    .git

git clone

    克隆一個遠端倉庫到本地目錄。

  • 概要
git clone [--template=<template_directory>]
      [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
      [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
      [--dissociate] [--separate-git-dir <git dir>]
      [--depth <depth>] [--[no-]single-branch] [--no-tags]
      [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
      [--jobs <n>] [--] <repository> [<directory>]
  • 描述
        克隆遠端倉庫到當前目錄,併為克隆下來的本地倉庫的每個分支建立遠端跟蹤分支(可使用git branch -r檢視),並從克隆檢出的儲存庫作為當前活動分支的初始分支。
        在克隆之後,沒有引數的普通git提取將更新所有遠端跟蹤分支,並且沒有引數的git pull將會把遠端主分支合併到當前主分支(如果有的話)。
  • 示例
$ git clone https://github.com/huangyangneng/demo.git

Cloning into 'demo'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

克隆完後,會在當前目錄下生成一個demo資料夾。進入demo資料夾,可以看到有一個.git目錄。

git add

    將修改過的檔案新增到快取區中

  • 摘要
git add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]
      [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
      [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize]
      [--chmod=(+|-)x] [--] [<pathspec>…​]
  • 描述
        此命令將修改過的檔案新增到到暫存區,作為下一次準備提交的內容。 它通常將現有路徑下的當前修改內容作為一個整體新增,但是通過一些選項,它也可以用於新增只對檔案進行一些更改,或刪除。
        暫存區儲存著當前修改內容的快照,並且將該快照作為下一個提交的內容。 因此,在對倉庫進行任何更改之後,並且在執行git commit命令之前,必須使用git add命令將任何新的或修改的檔案新增到暫存區中。
        該命令可以在提交之前多次執行。它只在執行git add命令時新增指定修改的內容; 如果希望隨後的更改包含在下一個提交中,那麼必須再次執行git add將新的內容新增到暫存區中。
        預設情況下,git add命令不會新增忽略的檔案。 如果在命令列上顯式指定了任何忽略的檔案,git add命令都將失敗,並顯示一個忽略的檔案列表。由Git執行的目錄遞迴或檔名遍歷所導致的忽略檔案將被預設忽略。 git add命令可以用-f(force)選項新增被忽略的檔案。
  • 示例
$ touch README.md
$ echo hello world > README.md
$ git add -A 

git add -u [<path>]:把<path>中所有跟蹤檔案中被修改過或已刪除檔案的資訊新增到暫存區。它不會處理那些不被跟蹤的檔案。省略<path>表示 . ,即當前目錄。
git add -A <path>:表示把中所有跟蹤檔案中被修改過或已刪除檔案和所有未跟蹤的檔案資訊新增到暫存區中。省略<path>表示 . ,即當前目錄。

git status

    檢視當前倉庫的狀態

  • 摘要
git status [<options>…​] [--] [<pathspec>…​]
  • 概述

    顯示倉庫中未被git commit過的所有檔案狀態資訊,包括被追蹤檔案的修改、刪除和新建未執行git add的未被追蹤的檔案。

  • 示例
        在每次執行 git commit之前先使用git status檢查檔案狀態是一個很好的習慣, 這樣能防止你不小心提交了您不想提交的東西。
        通過git status -uno可以只列出所有已經被git管理的且被修改但沒提交的檔案。
        通過git status -s以獲得簡短的結果輸出,如果沒加該引數會詳細輸出內容.
$ git status 


On branch master

Initial commit

Changes to be committed: (已經在stage區, 等待新增到HEAD中的檔案)
  (use "git rm --cached <file>..." to unstage) 

    new file:   README.md
    new file:   test.txt

Changes not staged for commit:(有修改, 但是沒有被新增到stage區的檔案)
  (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:(沒有tracked過的檔案, 即從沒有add過的檔案)
  (use "git add <file>..." to include in what will be committed)

    hello.txt

git diff

    用來顯示已寫入快取與已修改但尚未寫入快取的改動的區別。此命令比較的是工作目錄中當前檔案和暫存區域快照之間的差異,也就是修改之後還沒有暫存起來的變化內容。

  • 摘要
git diff [options] [<commit>] [--] [<path>…​]
git diff [options] --cached [<commit>] [--] [<path>…​]
git diff [options] <commit> <commit> [--] [<path>…​]
git diff [options] <blob> <blob>
git diff [options] [--no-index] [--] <path> <path>
  • 概述

    顯示工作樹和索引或樹之間的變化,索引和樹之間的變化,兩棵樹之間的變化,兩個blob物件之間的變化,或者磁碟上兩個檔案之間的變化。

  • 示例
    • 比較工作區和暫存區域之間的差異也就是修改之後還沒有暫存起來的變化內容:git diff
    • 比較當前檔案和暫存區檔案差異:git diff <file>
    • 比較兩次提交之間的差異:git diff id1 id2
    • 在兩個分支之間比較:git diff branch1 branch2
    • 比較暫存區和版本庫差異:git diff --staged
    • 檢視已快取的改動: git diff --cached
    • 檢視已快取的與未快取的所有改動:git diff HEAD
    • 僅僅比較統計資訊:git diff --stat
# 比較工作區和暫存區域之間的差異
$ git diff

diff --git a/hello.txt b/hello.txt
index ce01362..b1d9f39 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
 hello
+git diff

# 比較當前檔案和暫存區檔案差異
$ git diff test.txt

diff --git a/test.txt b/test.txt
index ed894ce..3b68ed8 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
 test
 dte
+git diff test

# 比較兩次提交之間的差異

$ git diff 7e7c298660207f30568dcd5efc127392988916e1 fb89408bc73a5ebaa8fa0536ddadda7a92b07f0f

diff --git a/test.txt b/test.txt
index ed894ce..9daeafb 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1 @@
 test
-dte

# 檢視已快取的與未快取的所有改動
$ git diff HEAD

diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..b1d9f39
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1,2 @@
+hello
+git diff
diff --git a/test.txt b/test.txt
index ed894ce..3b68ed8 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
 test
 dte
+git diff testg

# 比較統計資訊
$ git diff --stat

hello.txt | 1 +
 test.txt  | 1 +
 2 files changed, 2 insertions(+)

git commit

    將快取區內容新增到倉庫中

  • 摘要
git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]
       [--dry-run] [(-c | -C | --fixup | --squash) <commit>]
       [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
       [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
       [--date=<date>] [--cleanup=<mode>] [--[no-]status]
       [-i | -o] [-S[<keyid>]] [--] [<file>…​]
  • 概述

    git commit命令將暫存區的當前內容與描述更改的使用者和日誌訊息一起儲存在新的提交中。
要新增的內容可以通過以下幾種方式指定:

  • 在使用git commit命令之前,通過使用git add將工作區的內容新增到暫存區;

  • 通過使用帶有-a選項的git commit命令來新增從所有已知檔案(即所有已經在暫存區中列出的檔案),並自動從工作樹中刪除執行過“git rm”的檔案;

  • 通過使用git rm從工作樹和暫存區中刪除檔案,再次使用git commit命令;

  • 通過將檔案作為引數列出到git commit命令(不使用--interactive--patch選項),在這種情況下,提交將忽略暫存區中分段的更改,而是記錄列出的檔案的當前內容;

  • 通過使用--interactive--patch選項與git commit命令一起確定除了暫存區中的內容之外哪些檔案應該是提交的一部分,然後才能完成操作。

  • 示例

$ vi commit.xt #新增檔案,檔案內容為commit
$ git status #檢視當前狀態

On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    commit.txt

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

$ git add commit.txt #提交到暫存區
$ git status #檢視當前狀態

On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   commit.txt

$ git commit -m "add commit.txt" #提交修改

[master deb9eb3] add commit.txt
 1 file changed, 1 insertion(+)
 create mode 100644 commit.txt

$ git status #檢視當前狀態
On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
nothing to commit, working directory clean

$ git log #檢視提交記錄
commit deb9eb3cd2ec92b12417b8d20db884db7d4a7711
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 11:10:21 2018 +0800

    add commit.txt

git log

    檢視歷史提交記錄

  • 摘要
git log [<options>] [<revision range>] [[\--] <path>…​]
  • 概述

    該命令採用適用於git rev-list命令的選項來控制顯示的內容以及適用於git diff- *命令的選項來控制每個提交的更改是如何顯示的。

  • 示例
    • 顯示提交歷史:git log
    • 檢視歷史記錄的簡潔的版本:git log --oneline
    • 檢視所有未被合併過的提交資訊:git log --no-merges
    • 檢視所有合併過的提交歷史記錄:git log --merges
    • 檢視歷史中什麼時候出現了分支、合併:git log g--oneline --graph
    • 逆向顯示所有日誌:git log --reverse --oneline
    • 查詢指定使用者的提交日誌:git log --author=huangyangneng --oneline
    • 顯示最近幾次的提交:git log -3
    • 顯示某次提交以及之前的記錄:git log commitId
    • 顯示指定時間之後的提交(不包含當前日期--since,--affter):git log --oneline --after={2018-04-18}
    • 顯示指定時間之前的提交(包含當前日期--until,--before):git log --oneline --before={1.day.ago}
$ git log 

 commit deb9eb3cd2ec92b12417b8d20db884db7d4a7711
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 11:10:21 2018 +0800

    add commit.txt

commit cebe2945e0262aace6df11f02e3d96156807a12e
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 11:09:19 2018 +0800

    add diff.txt

commit bbe2af51886d10268c7faabbaeff5b87634cc5cd
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 11:00:19 2018 +0800

    test

commit 6237009b04e1a4cb35bc4fa726834826035ea581
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 10:59:31 2018 +0800

    commit

commit 78ea960945cb7e5ed7c38e4129f6f3fa59a365f8
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 10:58:35 2018 +0800

    git commit test

commit 7e7c298660207f30568dcd5efc127392988916e1
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 10:14:43 2018 +0800

    test

commit fb89408bc73a5ebaa8fa0536ddadda7a92b07f0f
Author: huangyangneng <test@qq.com>
Date:   Sat May 26 10:14:16 2018 +0800

    test

$ git log --oneline #檢視歷史記錄的簡潔的版本

deb9eb3 add commit.txt
cebe294 add diff.txt
bbe2af5 test
6237009 commit
78ea960 git commit test
7e7c298 test
fb89408 test

$ git log --oneline -3 #顯示最近3次的提交

deb9eb3 add commit.txt
cebe294 add diff.txt
bbe2af5 test

$ git log --oneline --before={2018-05-26} #顯示2018-05-26之前的提交

deb9eb3 add commit.txt
cebe294 add diff.txt
bbe2af5 test
6237009 commit
78ea960 git commit test
7e7c298 test
fb89408 test

git reset

    用於將當前HEAD復位到指定狀態。一般用於撤消之前的一些操作。

  • 摘要
git reset [-q] [<tree-ish>] [--] <paths>…​
git reset (--patch | -p) [<tree-ish>] [--] [<paths>…​]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
  • 概述

    在第一和第二種形式中,將條目從<tree-ish>複製到索引。 在第三種形式中,將當前分支頭(HEAD)設定為<commit>,可選擇修改索引和工作樹進行匹配。所有形式的<tree-ish>/<commit>預設為 HEAD 。這裡的 HEAD 關鍵字指的是當前分支最末梢最新的一個提交。也就是版本庫中該分支上的最新版本。
    git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD]:將當前的分支重設(reset)到指定的<commit>或者HEAD(預設,如果不顯示指定<commit>,預設是HEAD,即最新的一次提交),並且根據[mode]有可能更新索引和工作目錄。mode的取值可以是hard、soft、mixed、merged、keep。

  • --hard:重設(reset) 索引和工作目錄,自從<commit>以來在工作目錄中的任何改變都被丟棄,並把HEAD指向<commit>。
  • --soft:不觸及索引檔案或工作樹(但重置HEAD到<commit>,就像所有模式一樣)。這使得所有更改後的狀態變成已暫存,如git status所示。當提交了之後,又發現程式碼沒有提交完整,或者想重新編輯一下提交的資訊,可執行git reset --soft HEAD^,讓工作目錄還跟reset之前一樣,不作任何改變。
  • --mixed:重置索引但不重置工作樹(即更改的檔案被保留為未標記提交),並報告未更新的內容。這是預設操作。
  • --merge:重置索引並更新工作樹中不同於<commit>和HEAD之間的檔案,但保留索引和工作樹之間不同的檔案(即那些沒有新增的更改)。即回退到<commit>之前的狀態,但是工作區的修改不被重置。如果在<commit>和索引之間不同的檔案有未分級的更改,則中止重置。
  • --keep:重置索引條目並更新工作樹中不同於<commit>和HEAD的檔案。如果在<commit>和HEAD之間不同的檔案有本地更改,則中止重置。
  • 示例
    • 回退暫存的檔案:git reset HEAD <file>
    • 回退到上一次提交版本: git reset --hard HEAD^
    • 回退到上上次提交版本: git reset --hard HEAD^^
    • 回退到上N次提交版本: git reset --hard HEAD~N
    • 回退到指定版本:git reset --hard <commitId>
$ vi reset.txt #新增檔案,內容為reset
$ git add reset.txt #新增檔案到暫存區
$ git status #檢視當前狀態

On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   reset.txt

$ git reset HEAD reset.txt #回退暫存的檔案
$ git status #檢視當前狀態

On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    reset.txt

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


git reflog

    可以檢視所有分支的所有操作記錄(包括提交、回退、已刪除的提交操作記錄等)。

  • 摘要
git reflog <subcommand> <options>
  • 概述

    git reflog 除了能檢視所有提交記錄外,還能檢視會退,已刪除等的操作記錄。git reflog 每行記錄都由版本號(commit id SHA),HEAD值和操作描述三部分組成。版本號在第一列,HEAD值在第二列,操作描述資訊在第三列。當我們會退出錯時,想回到某個新版本,就可以用git reflog 檢視對應的commitId,然後進行會退。

  • 版本號:標識著每一次提交、合併等操作時的版本,相當於唯一標識
  • HEAD值:同樣用來標識版本,但是不同於版本號的是,Head值是相對的。
    當HEAD值為HEAD時,表示為提交的最新版本;HEAD^表示為最新版本的上一個版本;HEAD^^表示為最新版本的上上個版本;HEAD~100表示為最新版本的往上第100個版本。HEAD值越小,表示版本越新,越大表示版本生成時間越久。
    在下面例子中,我們發現HEAD值的展示形式為HEAD@{0}、HEAD@{1}、HEAD@{2}...同樣HEAD值的數字越小,表示版本越新,數字越大表示版本越舊。
  • 操作描述:記錄了本次是哪種操作,以及操作時編寫的描述資訊。
  • 示例
    • 檢視歷史版本記錄:git reflog
    • 檢視歷史版本記錄-指定顯示條數:git reflog -n
    • 顯示指定時間之後的提交(不包含當前日期--since,--affter):git reflog --after={2018-04-18}
    • 顯示指定時間之前的提交(包含當前日期--until,--before):git reflog --before={1.day.ago}
$ git reflog

cebe294 HEAD@{0}: reset: moving to HEAD^
deb9eb3 HEAD@{1}: commit: add commit.txt
cebe294 HEAD@{2}: commit: add diff.txt
bbe2af5 HEAD@{3}: commit: test
6237009 HEAD@{4}: commit: commit
78ea960 HEAD@{5}: commit: git commit test
7e7c298 HEAD@{6}: commit: test
fb89408 HEAD@{7}: commit (initial): test

$ git reflog -3

cebe294 HEAD@{0}: reset: moving to HEAD^
deb9eb3 HEAD@{1}: commit: add commit.txt
cebe294 HEAD@{2}: commit: add diff.txt

$ git reflog --after={2018-05-25}

cebe294 HEAD@{0}: reset: moving to HEAD^
deb9eb3 HEAD@{1}: commit: add commit.txt
cebe294 HEAD@{2}: commit: add diff.txt
bbe2af5 HEAD@{3}: commit: test
6237009 HEAD@{4}: commit: commit
78ea960 HEAD@{5}: commit: git commit test
7e7c298 HEAD@{6}: commit: test
fb89408 HEAD@{7}: commit (initial): test

git rm

    用於從工作區和索引中刪除檔案。

  • 摘要
git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>…​
  • 概述

    從索引中刪除檔案,或從工作樹和索引中刪除檔案。 git rm不會從您的工作目錄中刪除檔案。 (沒有任何選項只能從工作樹中刪除檔案,並將其保留在索引中)要刪除的檔案必須與分支的提示相同,並且在索引中不能對其內容進行更新,儘管可以使用-f選項覆蓋(預設行為)。 當給出--cached時,暫存區內容必須與分支的提示或磁碟上的檔案相匹配,從而僅將檔案從索引中刪除。
    使用 git rm來刪除檔案,同時還會將這個刪除操作記錄下來;而使用 rm 來刪除檔案,僅僅是刪除了物理檔案,沒有將其從 git 的記錄中剔除。
    直觀的來講,git rm 刪除過的檔案,執行 git commit 提交時,會自動將刪除該檔案的操作提交上去。
    而對於用 rm命令直接刪除的檔案,執行 git commit 提交時,則不會將刪除該檔案的操作提交上去。不過不要緊,即使你已經通過 rm 將某個檔案刪除掉了,也可以再通過 git rm 命令重新將該檔案從 git 的記錄中刪除掉,這樣的話,在執行 git commit 以後,也能將這個刪除操作提交上去。
    如果之前不小心用 rm命令刪除了一大批檔案呢?如此時用 git rm 逐個地再刪除一次就顯得相當卵痛了。可如下的方式做提交:git commit -am "commit message or mark"

  • 示例
    • 刪除檔案:git rm <file>
    • 刪除資料夾:git rm <dir>
$ ls
README.md   commit.txt  diff.txt    reset.txt   reset2.txt  test.txt
$ git rm reset2.txt
$ git status

On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    reset2.txt

$ ls
README.md   commit.txt  diff.txt    reset.txt   test.txt

git mv

    用於移動或重新命名檔案,目錄或符號連結。

  • 摘要
git mv <options>…​ <args>…​
  • 概述

    移動或重新命名檔案,目錄或符號連結。移動檔案時,移動目錄必須存在。

  • 示例
    • 重新命名檔案:git mv <file1> <file2>
    • 移動檔案到指定目錄:git mv <file> <dir>
$ git mv reset.txt reset2.txt
$ git status 
On branch master
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    reset.txt -> reset2.txt

git pull

    用於從另一個儲存庫或本地分支獲取並整合(整合)。git pull命令的作用是:取回遠端主機某個分支的更新,再與本地的指定分支合併。

  • 摘要
git pull [options] [<repository> [<refspec>…​]]
  • 概述

    將遠端儲存庫中的更改合併到當前分支中。在預設模式下,git pullgit fetch後跟git merge FETCH_HEAD的縮寫。更準確地說,git pull使用給定的引數執行git fetch,並呼叫git merge將檢索到的分支頭合併到當前分支中。 如果使用--rebase,它執行是git rebase而不是git merge

  • 示例
$ git pull https://github.com/huangyangneng/demo.git master:master
Already up-to-date.

git push

    用於將本地分支的更新,推送到遠端倉庫。

  • 摘要
git push [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
       [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
       [-u | --set-upstream] [--push-option=<string>]
       [--[no-]signed|--signed=(true|false|if-asked)]
       [--force-with-lease[=<refname>[:<expect>]]]
       [--no-verify] [<repository> [<refspec>…​]]
  • 概述

    使用本地引用更新遠端引用,同時傳送完成給定引用所需的物件。可以在每次推入儲存庫時,通過在那裡設定掛鉤觸發一些事件。當命令列不指定使用<repository>引數推送的位置時,將查詢當前分支的branch.*.remote配置以確定要在哪裡推送。 如果配置丟失,則預設為origin。

  • 示例
    • 將本地的master分支推送到origin主機的master分支。如果master不存在,則會被新建:git push origin master
    • 當前分支與遠端分支之間存在追蹤關係,則本地分支和遠端分支都可以省略:git push origin
    • 如果當前分支只有一個追蹤分支,那麼主機名都可以省略:git push
    • 如果當前分支與多個主機存在追蹤關係,則可以使用-u選項指定一個預設主機,這樣後面就可以不加任何引數使用git pushgit push -u origin master
$ git push

Username for 'https://github.com': huangyangneng
Password for 'https://huangyangneng@github.com': 
Counting objects: 37, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (25/25), done.
Writing objects: 100% (37/37), 2.94 KiB | 0 bytes/s, done.
Total 37 (delta 7), reused 0 (delta 0)
remote: Resolving deltas: 100% (7/7), done.
To https://github.com/huangyangneng/demo.git
 * [new branch]      master -> master

分支管理

    幾乎所有的版本控制系統都以某種形式支援分支。 使用分支意味著你可以把你的工作從開發主線上分離開來,以免影響開發主線。 在很多版本控制系統中,這是一個略微低效的過程——常常需要完全建立一個原始碼目錄的副本。對於大專案來說,這樣的過程會耗費很多時間。
    Git 處理分支的方式可謂是難以置信的輕量,建立新分支這一操作幾乎能在瞬間完成,並且在不同分支之間的切換操作也是一樣便捷。
    當我們用git init初始化一個倉庫時,此時git會預設幫我們建立一個主分支,即master分支。以及一個指向master分支的HEAD指標。一開始,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:

8544948-4a3ff818c8e1d208.png

    每次提交,master分支都會向前移動一步,HEAD始終指向master。這樣,隨著你不斷提交,master分支的線也越來越長。
    但我們建立一個新的分支並切換到新分支時,比如branchtest,此時git會新建一個可移動的指標,叫做branchtest,指向master相同的位置,再把HEAD指向branchtest,就表示當前分支在branchtest上:
8544948-f51e38feb6773df8.png

    從上面我們可以看出,git建立分支是很快的,因為就建立了一個新的指標。切換分支也是很快的,因為就把HEAD指標指到對應的分支上面。
    然後我們在新的分支上修改提交,branchtest指標就向前移動,而master分支位置不變。
8544948-7c747a2d32bcc16c.png

    當我們在branchtest上面的工作做完後,就可以把branchtest分支合併到master分支了。git分支合併也很快,只需要把master指向當前的提交就完成了合併。
8544948-8fb94e0048561903.png

    當我們把branchtest分支合併到master分支後,如果不需要branchtest分支了,我們就可以刪除掉branchtest分支了,git刪除分支就是把branchtest指標刪除掉。
8544948-5fedabdf15b06358.png

branch

    用於列出,建立或刪除分支。

  • 摘要
git branch [--color[=<when>] | --no-color] [-r | -a]
    [--list] [-v [--abbrev=<length> | --no-abbrev]]
    [--column[=<options>] | --no-column] [--sort=<key>]
    [(--merged | --no-merged) [<commit>]]
    [--contains [<commit]] [--no-contains [<commit>]]
    [--points-at <object>] [--format=<format>] [<pattern>…​]
git branch [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
git branch (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
git branch --unset-upstream [<branchname>]
git branch (-m | -M) [<oldbranch>] <newbranch>
git branch (-c | -C) [<oldbranch>] <newbranch>
git branch (-d | -D) [-r] <branchname>…​
git branch --edit-description [<branchname>]
  • 概述

    如果給出了--list或者如果沒有非選項引數,則列出現有的分支; 當前分支將以星號突出顯示。 選項-r導致遠端跟蹤分支被列出,而選項-a顯示本地和遠端分支。 如果給出了一個<pattern>,它將被用作一個shell萬用字元,將輸出限制為匹配的分支。 如果給出多個模式,如果匹配任何模式,則顯示分支。 請注意,提供<pattern>時,必須使用--list; 否則命令被解釋為分支建立。

  • 示例
    • 檢視當前有哪些分支:git branch or git branch --list
    • 新建一個分支:git branch <branchName>
    • 切換到某一個分支:git checkout <branchName>
    • 檢視本地和遠端分支:git branch -a
    • 重新命名分支:git branch -m or -M <oldBranchName> <newBranchName>
    • 刪除分支:git branch -d or -D <branchName>
    • 刪除遠端分支:git branch -r -d origin/<branchName> and git push origin :<branchName>
#檢視當前有哪些分支
$ git branch
* master
#新建分支
$ git branch branchtest
$ git branch
  branchtest
* master
#切換到某個分只
$ git checkout branchtest
$ git branch
* branchtest
  master
#檢視本地和遠端分支
$ git branch -a 
* branchtest
  master
  remotes/origin/master
#重新命名分支
$ git branch -m branchtest branchtest1
$ git banch
  branchtest1
* master
#刪除分支
$ git branch -d branchtest1
Deleted branch branchtest1 (was 35306f2).
$ git branch
* master

git checkout

    用於切換分支或恢復工作樹檔案。

  • 摘要
git checkout [-q] [-f] [-m] [<branch>]
git checkout [-q] [-f] [-m] --detach [<branch>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>…​
git checkout [<tree-ish>] [--] <pathspec>…​
git checkout (-p|--patch) [<tree-ish>] [--] [<paths>…​]
  • 概述

    更新工作樹中的檔案以匹配索引或指定樹中的版本。如果沒有給出路徑,git checkout還會更新HEAD,將指定的分支設定為當前分支。

  • 示例
    • 切換到指定分支:git checkout branchName
    • 建立並切換到指定分支:git checkout -b branchName
    • 從另一個提交或分支中取出檔案:git checkout <commitId or branchName> <file>
    • 從快取區中恢復檔案:git checkout <file>,注意這個操作是不可逆的,當執行這個操作,會把工作區中當前檔案為快取的修改重置掉。
$ git checkout -b branchtest #建立並切換到branchtest分支
$ git branch #檢視所有的分支,當前分支前面有個*號

* branchtest
  master

$ git checkout master #切換到master分支
$ git branch

  branchtest
* master

$ vi reset2.txt #在branchtest 分支上新增一個檔案,內容為reset
$ git add reset2.txt
$ git commit -m "reset2.txt"
$ git checkout master
$ git checkout branchtest reset2.txt
$ ls #可以看的在master分支上也有reset2.txt檔案
README.md   commit.txt  diff.txt    reset.txt   reset2.txt  test.txt 

merge

    用於將兩個或兩個以上的分支合併一起。

  • 摘要
git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
    [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
    [--[no-]allow-unrelated-histories]
    [--[no-]rerere-autoupdate] [-m <msg>] [<commit>…​]
git merge --abort
git merge --continue
  • 概述

    將命名約定的更改合併到當前分支中。這個命令被git pull 合併來自另一個儲存庫的更改,並且可以手工使用以將更改從一個分支合併到另一個分支。

  • 示例
    • 合併分支到當前分支,自動進行新的提交: git merge <branchName>
    • 合併分支到當前分支中,但不要自動進行新的提交:git merge --no-commit <branchName>
    • 合併多個分支到當前分支:git merge <branchName1> <branchName2> <branchNameN> -m "message"
  • 檢視分支合併情況:git log --graph --pretty=oneline --abbrev-commit
#合併分支到當前分支,首先我們在branchtest分支新建一個檔案branchtest.txt,內容為branchtest,然後提交;再l s切換到master分支,進行合併,會發現master分支上有branchtest.txt檔案
$ echo "branchtest" > branchtest.txt
$ git add -A
$ git commit -m "new branchtest.txt"
[branchtest e4a8286] new branchtest.txt
 1 file changed, 1 insertion(+)
 create mode 100644 branchtest.txt
$ git checkout branchtest
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git merge branchtest
Updating 35306f2..e4a8286
Fast-forward
 branchtest.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 branchtest.txt
8544948-4bc5792bd257b63f.png
分支合併圖.png

mergetool

    用於執行合併衝突解決工具來解決合併衝突。

  • 摘要
git mergetool [--tool=<tool>] [-y | --[no-]prompt] [<file>…​]
  • 概述

    git mergetool命令用於執行合併衝突解決工具來解決合併衝突。使用git mergetool執行合併實用程式來解決合併衝突。它通常在git合併後執行。
    如果給出一個或多個<file>引數,則將執行合併工具程式來解決每個檔案的差異(跳過那些沒有衝突的檔案)。 指定目錄將包括該路徑中的所有未解析檔案。 如果沒有指定<file>名稱,git mergetool將在具有合併衝突的每個檔案上執行合併工具程式。

  • 示例
#首先我們分別進入branchtest 和branchtest2 分支,然後修改branchtest.txt檔案內容,並提交。然後切換到master分支,把這兩個分支合併到master,就會發現有衝突,然後我們用git mergetool解決合併衝突後,在提交;

$ git merge branchtest branchtest2 -m "merge branchtest branchtest2 to merge"
Trying simple merge with branchtest
Simple merge did not work, trying automatic merge.
Auto-merging branchtest.txt
ERROR: content conflict in branchtest.txt
fatal: merge program failed
Automated merge did not work.
Should not be doing an Octopus.
Merge with strategy octopus failed.
$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
tortoisemerge emerge vimdiff
Merging:
branchtest.txt

Normal merge conflict for 'branchtest.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (vimdiff):
#我們輸入檔名稱,然後可以看到檔案的衝突,我們修改完衝突後儲存再提交。
8544948-3277ec4c5bf75477.png
mergetool命令工具.png

git stash

    用於將更改儲藏在髒工作目錄中。

  • 摘要
git stash list [<options>]
git stash show [<stash>]
git stash drop [-q|--quiet] [<stash>]
git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
         [-u|--include-untracked] [-a|--all] [-m|--message <message>]
         [--] [<pathspec>…​]]
git stash clear
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
  • 概述

    當要記錄工作目錄和索引的當前狀態,但想要返回到乾淨的工作目錄時,則使用git stash。 該命令儲存本地修改,並恢復工作目錄以匹配HEAD提交。
    這個命令所儲藏的修改可以使用git stash list列出,使用git stash show進行檢查,並使用git stash apply恢復(可能在不同的提交之上)。呼叫沒有任何引數的git stash相當於git stash save。 預設情況下,儲藏列表為“分支名稱上的WIP”,但您可以在建立一個訊息時在命令列上給出更具描述性的訊息。

  • 示例
    • 把當前工作現場“儲藏”起來:git stash
    • 檢視現有的儲藏:git stash list
    • 恢復工作區:git stash apply(恢復) and git stash drop(刪除stash內容) or git stash pop(恢復並刪除stash內容)
$ git status

On branch master
Your branch is ahead of 'origin/master' by 12 commits.
  (use "git push" to publish your local commits)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   branchtest.txt

$ git stash

Saved working directory and index state WIP on master: 4391d47 test
HEAD is now at 4391d47 test

$ git status

On branch master
Your branch is ahead of 'origin/master' by 12 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

$ git stash list

stash@{0}: WIP on master: 4391d47 test

$ git stash pop

On branch master
Your branch is ahead of 'origin/master' by 12 commits.
  (use "git push" to publish your local commits)
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:   branchtest.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (c73b9457deff50245ba42fe6ac7e722c679ec43b)

標籤管理

git tag

    用於建立,列出,刪除或驗證使用GPG簽名的標籤物件。同大多數 VCS 一樣,Git 也可以對某一時間點上的版本打上標籤。在釋出某個軟體版本(比如 v1.0 等等)的時候,經常這麼做。

  • 摘要
git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] [-e]
    <tagname> [<commit> | <object>]
git tag -d <tagname>…​
git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
    [--points-at <object>] [--column[=<options>] | --no-column]
    [--create-reflog] [--sort=<key>] [--format=<format>]
    [--[no-]merged [<commit>]] [<pattern>…​]
git tag -v [--format=<format>] <tagname>…​
  • 概述

    在refs/tags/中新增標籤引用,除此之外還可以提供了-d/-l/-v來刪除,列出或驗證標籤。
    tag 用於建立一個標籤用於在開發階段,某個階段的完成,建立一個版本,在開發中都會使用到, 可以建立一個tag來指向軟體開發中的一個關鍵時期,比如版本號更新的時候可以建一個version1.0, version1.2之類的標籤,這樣在以後回顧的時候會比較方便。除非指定-f選項,否則不能建立已經存在的標籤。
    如果傳遞了-a-s-u <keyid>中的一個,該命令將建立一個標籤物件,並且需要一個標籤訊息。 除非-m <msg>-F <file>,否則將啟動一個編輯器,供使用者輸入標籤訊息。

  • 示例
    • 建立標籤(預設為HEAD,也可以指定一個commit id):git tag <tagName> or git tag -a <tagName> -m "標籤說明" or git tag <tagName> <commitId>
    • 列顯已有的標籤:git tag or git tag -l <tagName>(列出指定的標籤)
    • 刪除標籤:git tag -d <tagName>
#新建標籤
$ git tag -a v1.0.0 -m "first tag"
# 列出也有標籤
$ git tag
v1.0.0
# git show 命令檢視相應標籤的版本資訊,並連同顯示打標籤時的提交物件。
$ git show v1.0.0
tag v1.0.0
Tagger: huangyangneng <test@qq.com>
Date:   Tue May 29 16:21:58 2018 +0800

first tag

commit 3e579e852686a0614ea0f98e65cc8a74d6aaf872
Merge: 8b6af52 eb9766f 29e1a25
Author: huangyangneng <test@qq.com>
Date:   Tue May 29 15:12:15 2018 +0800

    update branchtest

diff --cc branchtest.txt
index 693fd50,26c1c20,0d5c17e..8a1c860
--- a/branchtest.txt
+++ b/branchtest.txt
@@@@ -1,1 -1,2 -1,2 +1,3 @@@@
   branchtest
+ +test
++ tesetset
localhost:demo huangyangneng
#刪除標籤
$ git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 37b4083)

    整理文章主要為了自己日後複習用,文章中可能會引用到別的博主的文章,如涉及到博主的版權問題,請博主聯絡我。

相關文章