簡介
- Git是一個開源的分布式版本控制系統(tǒng),用于敏捷高效地處理任何或小或大的項目。
- Git 與常用的版本控制工具 CVS, SVN 等不同,它采用了分布式版本庫的方式,不必服務(wù)器端軟件支持。
SVN 區(qū)別點
- GIT是分布式的,SVN不是,這是GIT和其它非分布式的版本控制系統(tǒng),例如SVN,CVS等,最核心的區(qū)別。
- GIT把內(nèi)容按元數(shù)據(jù)方式存儲,而SVN是按文件:所有的資源控制系統(tǒng)都是把文件的元信息隱藏在一個類似.svn,.cvs等的文件夾里。即GIT管理的是修改,而SVN管理的是文件。
- GIT分支和SVN的分支不同:分支在SVN中一點不特別,就是版本庫中的另外的一個目錄。
- GIT沒有一個全局的版本號,而SVN有:目前為止這是跟SVN相比GIT缺少的最大的一個特征。
- GIT的內(nèi)容完整性要優(yōu)于SVN:GIT的內(nèi)容存儲使用的是SHA-1哈希算法。這能確保代碼內(nèi)容的完整性,確保在遇到磁盤故障和網(wǎng)絡(luò)問題時降低對版本庫的破壞。
配置
Git 提供了一個叫做 git config 的工具,專門用來配置或讀取相應(yīng)的工作環(huán)境變量。
三種不同級別的配置
- git config --system
????系統(tǒng)用戶級別所擁有的倉庫配置值,基本不用到 - git config --global
????全局的倉庫配置值,會去讀寫每個用戶下的~/.gitconfig文件 - git config --local
????局部的倉庫配置值,會去讀寫某個項目下的.git/config文件
設(shè)置用戶信息
????設(shè)置用戶名和郵箱,配置的用戶名和郵件地址將在版本庫提交時作為提交者的用戶名和郵件地址。
git config --global user.name "hyn"
git config --global user.email "example@qq.com"
????如果用 --global選項,那么更改的配置文件就是位于你用戶主目錄下的那個配置,以后你所有的項目都會默認(rèn)使用這里配置的用戶信息。
????如果要在某個特定的項目中使用其他名字或者郵箱,只要在對應(yīng)的項目目錄下去掉--global選項重新配置或者在對應(yīng)的項目目錄下把--global 換成--local即可,新的設(shè)定保存在當(dāng)前項目的 .git/config 文件里。
設(shè)置別名
????可通過alias去修改git命令的別名
-
git status
是用來查看文件修改的命令,可以用git st 代替 -
git pull
是用來拉取遠(yuǎn)程倉庫代碼的命令,可以用git pl 代替 -
git push
是用來將本地修改推送到遠(yuǎn)程倉庫的命令,可以用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
????查找某個變量的設(shè)置:git config --local user.name
hyn
工作區(qū)、暫存區(qū)和版本庫
基本概念
工作區(qū):你電腦里項目的目錄。
暫存區(qū):英文叫stage,一般存放在”git目錄”下的index文件(.git/index)中,所以我們把暫存區(qū)有時也叫作索引(index)。
-
版本庫:工作區(qū)有一個隱藏目錄.git,這個不算工作區(qū),而是Git的版本庫。
工作區(qū)、暫存區(qū)和版本庫之間的關(guān)系.png 圖中左側(cè)為工作區(qū),右側(cè)為版本庫。在版本庫中標(biāo)記為 stage的區(qū)域是暫存區(qū),標(biāo)記為master的是項目的master分支。
圖中我們可以看出此時HEAD實際是指向 master 分支的一個游標(biāo)。所以圖示的命令中出現(xiàn) HEAD 的地方可以用 master 來替換。
當(dāng)對工作區(qū)修改的文件執(zhí)行
git add
命令時,暫存區(qū)的目錄樹被更新即把工作區(qū)的修改添加到暫存區(qū);當(dāng)執(zhí)行提交操作git commit
時,暫存區(qū)的目錄樹寫到版本庫中,master 分支會做相應(yīng)的更新。即把暫存區(qū)的內(nèi)容提交到當(dāng)前分支當(dāng)執(zhí)行
git reset HEAD
命令時,暫存區(qū)的目錄樹會被重寫,被 master 分支指向的目錄樹所替換,但是工作區(qū)不受影響。當(dāng)執(zhí)行
git rm --cached <file>
命令時,會直接從暫存區(qū)刪除文件,工作區(qū)則不做出改變。當(dāng)執(zhí)行
git checkout .
或者git checkout -- <file>
命令時,會用暫存區(qū)全部或指定的文件替換工作區(qū)的文件。這個操作很危險,會清除工作區(qū)中未添加到暫存區(qū)的改動。當(dāng)執(zhí)行
git checkout HEAD .
或者git checkout HEAD <file>
命令時,會用 HEAD 指向的 master 分支中的全部或者部分文件替換暫存區(qū)和以及工作區(qū)中的文件。這個命令也是極具危險性的,因為不但會清除工作區(qū)中未提交的改動,也會清除暫存區(qū)中未提交的改動。
版本庫
????版本庫又名倉庫,英文名repository,可以簡單理解成一個目錄,這個目錄里面的所有文件都可以被Git管理起來,每個文件的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。
新建本地倉庫
????使用 git init
命令來初始化一個 Git 倉庫, 在執(zhí)行完成 git init 命令后,Git 倉庫會生成一個 .git 目錄,該目錄包含了資源的所有元數(shù)據(jù),其他的項目目錄保持不變。
- 使用當(dāng)前目錄作為倉庫:
git init
- 使用執(zhí)行目錄作為倉庫:
git init 目錄地址
復(fù)制遠(yuǎn)程倉庫
????使用 git clone
從現(xiàn)有的遠(yuǎn)程倉庫中拷貝項目
- 當(dāng)前目錄下拷貝:
git clone 倉庫地址
- 拷貝到指定目錄:
git clone 倉庫地址 目錄地址
基本操作
git init
????創(chuàng)建一個空的Git存儲庫或重新初始化一個現(xiàn)有的存儲庫。
- 摘要
git init [-q | --quiet] [--bare] [--template=<template_directory>]
[--separate-git-dir <git dir>]
[--shared[=<permissions>]] [directory]
- 描述
????此命令創(chuàng)建一個空的Git存儲庫,會在當(dāng)前目錄下生成一個.git目錄,該目錄下包含objects, refs/heads, refs/tags和模版文件。該命令還創(chuàng)建了一個master分支,以及指向master的一個指針叫HEAD。 - 示例
$ mkdir demo
$ cd demo
$ git init
Initialized empty Git repository in /Users/huangyangneng/Documents/workspace/git/demo/.git/
在demo目錄下創(chuàng)建了一個空的git倉庫
$ ls -a
. .. .git
git clone
????克隆一個遠(yuǎn)程倉庫到本地目錄。
- 概要
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>]
- 描述
????克隆遠(yuǎn)程倉庫到當(dāng)前目錄,并為克隆下來的本地倉庫的每個分支創(chuàng)建遠(yuǎn)程跟蹤分支(可使用git branch -r
查看),并從克隆檢出的存儲庫作為當(dāng)前活動分支的初始分支。
????在克隆之后,沒有參數(shù)的普通git提取將更新所有遠(yuǎn)程跟蹤分支,并且沒有參數(shù)的git pull將會把遠(yuǎn)程主分支合并到當(dāng)前主分支(如果有的話)。 - 示例
$ git clone https://github.com/huangyangneng/demo.git
Cloning into 'demo'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
克隆完后,會在當(dāng)前目錄下生成一個demo文件夾。進入demo文件夾,可以看到有一個.git目錄。
git add
????將修改過的文件添加到緩存區(qū)中
- 摘要
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>…?]
- 描述
????此命令將修改過的文件添加到到暫存區(qū),作為下一次準(zhǔn)備提交的內(nèi)容。 它通常將現(xiàn)有路徑下的當(dāng)前修改內(nèi)容作為一個整體添加,但是通過一些選項,它也可以用于添加只對文件進行一些更改,或刪除。
????暫存區(qū)保存著當(dāng)前修改內(nèi)容的快照,并且將該快照作為下一個提交的內(nèi)容。 因此,在對倉庫進行任何更改之后,并且在運行git commit
命令之前,必須使用git add
命令將任何新的或修改的文件添加到暫存區(qū)中。
????該命令可以在提交之前多次執(zhí)行。它只在運行git add
命令時添加指定修改的內(nèi)容; 如果希望隨后的更改包含在下一個提交中,那么必須再次運行git add
將新的內(nèi)容添加到暫存區(qū)中。
????默認(rèn)情況下,git add
命令不會添加忽略的文件。 如果在命令行上顯式指定了任何忽略的文件,git add
命令都將失敗,并顯示一個忽略的文件列表。由Git執(zhí)行的目錄遞歸或文件名遍歷所導(dǎo)致的忽略文件將被默認(rèn)忽略。git add
命令可以用-f(force)選項添加被忽略的文件。 - 示例
$ touch README.md
$ echo hello world > README.md
$ git add -A
git add -u [<path>]:把<path>中所有跟蹤文件中被修改過或已刪除文件的信息添加到暫存區(qū)。它不會處理那些不被跟蹤的文件。省略<path>表示 . ,即當(dāng)前目錄。
git add -A <path>:表示把中所有跟蹤文件中被修改過或已刪除文件和所有未跟蹤的文件信息添加到暫存區(qū)中。省略<path>表示 . ,即當(dāng)前目錄。
git status
????查看當(dāng)前倉庫的狀態(tài)
- 摘要
git status [<options>…?] [--] [<pathspec>…?]
- 概述
????顯示倉庫中未被git commit
過的所有文件狀態(tài)信息,包括被追蹤文件的修改、刪除和新建未執(zhí)行git add
的未被追蹤的文件。
- 示例
????在每次執(zhí)行git commit
之前先使用git status檢查文件狀態(tài)是一個很好的習(xí)慣, 這樣能防止你不小心提交了您不想提交的東西。
????通過git status -uno
可以只列出所有已經(jīng)被git管理的且被修改但沒提交的文件。
????通過git status -s
以獲得簡短的結(jié)果輸出,如果沒加該參數(shù)會詳細(xì)輸出內(nèi)容.
$ git status
On branch master
Initial commit
Changes to be committed: (已經(jīng)在stage區(qū), 等待添加到HEAD中的文件)
(use "git rm --cached <file>..." to unstage)
new file: README.md
new file: test.txt
Changes not staged for commit:(有修改, 但是沒有被添加到stage區(qū)的文件)
(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
????用來顯示已寫入緩存與已修改但尚未寫入緩存的改動的區(qū)別。此命令比較的是工作目錄中當(dāng)前文件和暫存區(qū)域快照之間的差異,也就是修改之后還沒有暫存起來的變化內(nèi)容。
- 摘要
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對象之間的變化,或者磁盤上兩個文件之間的變化。
- 示例
- 比較工作區(qū)和暫存區(qū)域之間的差異也就是修改之后還沒有暫存起來的變化內(nèi)容:git diff
- 比較當(dāng)前文件和暫存區(qū)文件差異:
git diff <file>
- 比較兩次提交之間的差異:
git diff id1 id2
- 在兩個分支之間比較:
git diff branch1 branch2
- 比較暫存區(qū)和版本庫差異:
git diff --staged
- 查看已緩存的改動:
git diff --cached
- 查看已緩存的與未緩存的所有改動:
git diff HEAD
- 僅僅比較統(tǒng)計信息:
git diff --stat
# 比較工作區(qū)和暫存區(qū)域之間的差異
$ 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
# 比較當(dāng)前文件和暫存區(qū)文件差異
$ 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
# 比較統(tǒng)計信息
$ git diff --stat
hello.txt | 1 +
test.txt | 1 +
2 files changed, 2 insertions(+)
git commit
????將緩存區(qū)內(nèi)容添加到倉庫中
- 摘要
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
命令將暫存區(qū)的當(dāng)前內(nèi)容與描述更改的用戶和日志消息一起存儲在新的提交中。
要添加的內(nèi)容可以通過以下幾種方式指定:
在使用
git commit
命令之前,通過使用git add
將工作區(qū)的內(nèi)容添加到暫存區(qū);通過使用帶有
-a
選項的git commit
命令來添加從所有已知文件(即所有已經(jīng)在暫存區(qū)中列出的文件),并自動從工作樹中刪除執(zhí)行過“git rm
”的文件;通過使用
git rm
從工作樹和暫存區(qū)中刪除文件,再次使用git commit
命令;通過將文件作為參數(shù)列出到
git commit
命令(不使用--interactive
或--patch
選項),在這種情況下,提交將忽略暫存區(qū)中分段的更改,而是記錄列出的文件的當(dāng)前內(nèi)容;通過使用
--interactive
或--patch
選項與git commit
命令一起確定除了暫存區(qū)中的內(nèi)容之外哪些文件應(yīng)該是提交的一部分,然后才能完成操作。示例
$ vi commit.xt #添加文件,文件內(nèi)容為commit
$ git status #查看當(dāng)前狀態(tài)
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 #提交到暫存區(qū)
$ git status #查看當(dāng)前狀態(tài)
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 #查看當(dāng)前狀態(tài)
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
命令的選項來控制顯示的內(nèi)容以及適用于git diff- *
命令的選項來控制每個提交的更改是如何顯示的。
- 示例
- 顯示提交歷史:
git log
- 查看歷史記錄的簡潔的版本:
git log --oneline
- 查看所有未被合并過的提交信息:
git log --no-merges
- 查看所有合并過的提交歷史記錄:
git log --merges
- 查看歷史中什么時候出現(xiàn)了分支、合并:
git log g--oneline --graph
- 逆向顯示所有日志:
git log --reverse --oneline
- 查找指定用戶的提交日志:
git log --author=huangyangneng --oneline
- 顯示最近幾次的提交:
git log -3
- 顯示某次提交以及之前的記錄:
git log commitId
- 顯示指定時間之后的提交(不包含當(dāng)前日期
--since,--affter
):git log --oneline --after={2018-04-18}
- 顯示指定時間之前的提交(包含當(dāng)前日期--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
????用于將當(dāng)前HEAD復(fù)位到指定狀態(tài)。一般用于撤消之前的一些操作。
- 摘要
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>復(fù)制到索引。 在第三種形式中,將當(dāng)前分支頭(HEAD)設(shè)置為<commit>,可選擇修改索引和工作樹進行匹配。所有形式的<tree-ish>/<commit>默認(rèn)為 HEAD 。這里的 HEAD 關(guān)鍵字指的是當(dāng)前分支最末梢最新的一個提交。也就是版本庫中該分支上的最新版本。
????git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD]
:將當(dāng)前的分支重設(shè)(reset)到指定的<commit>或者HEAD(默認(rèn),如果不顯示指定<commit>,默認(rèn)是HEAD,即最新的一次提交),并且根據(jù)[mode]有可能更新索引和工作目錄。mode的取值可以是hard、soft、mixed、merged、keep。
- --hard:重設(shè)(reset) 索引和工作目錄,自從<commit>以來在工作目錄中的任何改變都被丟棄,并把HEAD指向<commit>。
- --soft:不觸及索引文件或工作樹(但重置HEAD到<commit>,就像所有模式一樣)。這使得所有更改后的狀態(tài)變成已暫存,如
git status
所示。當(dāng)提交了之后,又發(fā)現(xiàn)代碼沒有提交完整,或者想重新編輯一下提交的信息,可執(zhí)行g(shù)it reset --soft HEAD^,讓工作目錄還跟reset之前一樣,不作任何改變。 - --mixed:重置索引但不重置工作樹(即更改的文件被保留為未標(biāo)記提交),并報告未更新的內(nèi)容。這是默認(rèn)操作。
- --merge:重置索引并更新工作樹中不同于<commit>和HEAD之間的文件,但保留索引和工作樹之間不同的文件(即那些沒有添加的更改)。即回退到<commit>之前的狀態(tài),但是工作區(qū)的修改不被重置。如果在<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 #添加文件,內(nèi)容為reset
$ git add reset.txt #添加文件到暫存區(qū)
$ git status #查看當(dāng)前狀態(tài)
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 #查看當(dāng)前狀態(tài)
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值在第二列,操作描述信息在第三列。當(dāng)我們會退出錯時,想回到某個新版本,就可以用git reflog
查看對應(yīng)的commitId,然后進行會退。
- 版本號:標(biāo)識著每一次提交、合并等操作時的版本,相當(dāng)于唯一標(biāo)識
- HEAD值:同樣用來標(biāo)識版本,但是不同于版本號的是,Head值是相對的。
當(dāng)HEAD值為HEAD時,表示為提交的最新版本;HEAD^表示為最新版本的上一個版本;HEAD^^表示為最新版本的上上個版本;HEAD~100表示為最新版本的往上第100個版本。HEAD值越小,表示版本越新,越大表示版本生成時間越久。
在下面例子中,我們發(fā)現(xiàn)HEAD值的展示形式為HEAD@{0}、HEAD@{1}、HEAD@{2}...同樣HEAD值的數(shù)字越小,表示版本越新,數(shù)字越大表示版本越舊。 - 操作描述:記錄了本次是哪種操作,以及操作時編寫的描述信息。
- 示例
- 查看歷史版本記錄:
git reflog
- 查看歷史版本記錄-指定顯示條數(shù):
git reflog -n
- 顯示指定時間之后的提交(不包含當(dāng)前日期
--since,--affter
):git reflog --after={2018-04-18}
- 顯示指定時間之前的提交(包含當(dāng)前日期--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
????用于從工作區(qū)和索引中刪除文件。
- 摘要
git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>…?
- 概述
????從索引中刪除文件,或從工作樹和索引中刪除文件。 git rm
不會從您的工作目錄中刪除文件。 (沒有任何選項只能從工作樹中刪除文件,并將其保留在索引中)要刪除的文件必須與分支的提示相同,并且在索引中不能對其內(nèi)容進行更新,盡管可以使用-f
選項覆蓋(默認(rèn)行為)。 當(dāng)給出--cached
時,暫存區(qū)內(nèi)容必須與分支的提示或磁盤上的文件相匹配,從而僅將文件從索引中刪除。
????使用 git rm
來刪除文件,同時還會將這個刪除操作記錄下來;而使用 rm
來刪除文件,僅僅是刪除了物理文件,沒有將其從 git 的記錄中剔除。
????直觀的來講,git rm
刪除過的文件,執(zhí)行 git commit
提交時,會自動將刪除該文件的操作提交上去。
????而對于用 rm
命令直接刪除的文件,執(zhí)行 git commit
提交時,則不會將刪除該文件的操作提交上去。不過不要緊,即使你已經(jīng)通過 rm 將某個文件刪除掉了,也可以再通過 git rm
命令重新將該文件從 git 的記錄中刪除掉,這樣的話,在執(zhí)行 git commit
以后,也能將這個刪除操作提交上去。
????如果之前不小心用 rm
命令刪除了一大批文件呢?如此時用 git rm
逐個地再刪除一次就顯得相當(dāng)卵痛了。可如下的方式做提交: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
命令的作用是:取回遠(yuǎn)程主機某個分支的更新,再與本地的指定分支合并。
- 摘要
git pull [options] [<repository> [<refspec>…?]]
- 概述
????將遠(yuǎn)程存儲庫中的更改合并到當(dāng)前分支中。在默認(rèn)模式下,git pull
是git fetch
后跟git merge FETCH_HEAD
的縮寫。更準(zhǔn)確地說,git pull
使用給定的參數(shù)運行git fetch
,并調(diào)用git merge
將檢索到的分支頭合并到當(dāng)前分支中。 如果使用--rebase
,它運行是git rebase
而不是git merge
。
- 示例
$ git pull https://github.com/huangyangneng/demo.git master:master
Already up-to-date.
git push
????用于將本地分支的更新,推送到遠(yuǎn)程倉庫。
- 摘要
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>…?]]
- 概述
????使用本地引用更新遠(yuǎn)程引用,同時發(fā)送完成給定引用所需的對象。可以在每次推入存儲庫時,通過在那里設(shè)置掛鉤觸發(fā)一些事件。當(dāng)命令行不指定使用<repository>參數(shù)推送的位置時,將查詢當(dāng)前分支的branch.*.remote配置以確定要在哪里推送。 如果配置丟失,則默認(rèn)為origin。
- 示例
- 將本地的master分支推送到origin主機的master分支。如果master不存在,則會被新建:
git push origin master
- 當(dāng)前分支與遠(yuǎn)程分支之間存在追蹤關(guān)系,則本地分支和遠(yuǎn)程分支都可以省略:
git push origin
- 如果當(dāng)前分支只有一個追蹤分支,那么主機名都可以省略:
git push
- 如果當(dāng)前分支與多個主機存在追蹤關(guān)系,則可以使用-u選項指定一個默認(rèn)主機,這樣后面就可以不加任何參數(shù)使用
git push
:git push -u origin master
- 將本地的master分支推送到origin主機的master分支。如果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
分支管理
????幾乎所有的版本控制系統(tǒng)都以某種形式支持分支。 使用分支意味著你可以把你的工作從開發(fā)主線上分離開來,以免影響開發(fā)主線。 在很多版本控制系統(tǒng)中,這是一個略微低效的過程——常常需要完全創(chuàng)建一個源代碼目錄的副本。對于大項目來說,這樣的過程會耗費很多時間。
????Git 處理分支的方式可謂是難以置信的輕量,創(chuàng)建新分支這一操作幾乎能在瞬間完成,并且在不同分支之間的切換操作也是一樣便捷。
????當(dāng)我們用git init
初始化一個倉庫時,此時git會默認(rèn)幫我們創(chuàng)建一個主分支,即master分支。以及一個指向master分支的HEAD指針。一開始,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當(dāng)前分支,以及當(dāng)前分支的提交點:
????每次提交,master分支都會向前移動一步,HEAD始終指向master。這樣,隨著你不斷提交,master分支的線也越來越長。
????但我們創(chuàng)建一個新的分支并切換到新分支時,比如branchtest,此時git會新建一個可移動的指針,叫做branchtest,指向master相同的位置,再把HEAD指向branchtest,就表示當(dāng)前分支在branchtest上:
????從上面我們可以看出,git創(chuàng)建分支是很快的,因為就創(chuàng)建了一個新的指針。切換分支也是很快的,因為就把HEAD指針指到對應(yīng)的分支上面。
????然后我們在新的分支上修改提交,branchtest指針就向前移動,而master分支位置不變。
????當(dāng)我們在branchtest上面的工作做完后,就可以把branchtest分支合并到master分支了。git分支合并也很快,只需要把master指向當(dāng)前的提交就完成了合并。
????當(dāng)我們把branchtest分支合并到master分支后,如果不需要branchtest分支了,我們就可以刪除掉branchtest分支了,git刪除分支就是把branchtest指針刪除掉。
branch
????用于列出,創(chuàng)建或刪除分支。
- 摘要
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
或者如果沒有非選項參數(shù),則列出現(xiàn)有的分支; 當(dāng)前分支將以星號突出顯示。 選項-r
導(dǎo)致遠(yuǎn)程跟蹤分支被列出,而選項-a
顯示本地和遠(yuǎn)程分支。 如果給出了一個<pattern>,它將被用作一個shell通配符,將輸出限制為匹配的分支。 如果給出多個模式,如果匹配任何模式,則顯示分支。 請注意,提供<pattern>時,必須使用--list
; 否則命令被解釋為分支創(chuàng)建。
- 示例
- 查看當(dāng)前有哪些分支:
git branch or git branch --list
- 新建一個分支:
git branch <branchName>
- 切換到某一個分支:
git checkout <branchName>
- 查看本地和遠(yuǎn)程分支:
git branch -a
- 重命名分支:
git branch -m or -M <oldBranchName> <newBranchName>
- 刪除分支:
git branch -d or -D <branchName>
- 刪除遠(yuǎn)程分支:
git branch -r -d origin/<branchName>
andgit push origin :<branchName>
- 查看當(dāng)前有哪些分支:
#查看當(dāng)前有哪些分支
$ git branch
* master
#新建分支
$ git branch branchtest
$ git branch
branchtest
* master
#切換到某個分只
$ git checkout branchtest
$ git branch
* branchtest
master
#查看本地和遠(yuǎn)程分支
$ 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
????用于切換分支或恢復(fù)工作樹文件。
- 摘要
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,將指定的分支設(shè)置為當(dāng)前分支。
- 示例
- 切換到指定分支:
git checkout branchName
- 創(chuàng)建并切換到指定分支:
git checkout -b branchName
- 從另一個提交或分支中取出文件:
git checkout <commitId or branchName> <file>
- 從緩存區(qū)中恢復(fù)文件:
git checkout <file>
,注意這個操作是不可逆的,當(dāng)執(zhí)行這個操作,會把工作區(qū)中當(dāng)前文件為緩存的修改重置掉。
- 切換到指定分支:
$ git checkout -b branchtest #創(chuàng)建并切換到branchtest分支
$ git branch #查看所有的分支,當(dāng)前分支前面有個*號
* branchtest
master
$ git checkout master #切換到master分支
$ git branch
branchtest
* master
$ vi reset2.txt #在branchtest 分支上新增一個文件,內(nèi)容為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
- 概述
????將命名約定的更改合并到當(dāng)前分支中。這個命令被git pull 合并來自另一個存儲庫的更改,并且可以手工使用以將更改從一個分支合并到另一個分支。
- 示例
- 合并分支到當(dāng)前分支,自動進行新的提交:
git merge <branchName>
- 合并分支到當(dāng)前分支中,但不要自動進行新的提交:
git merge --no-commit <branchName>
- 合并多個分支到當(dāng)前分支:
git merge <branchName1> <branchName2> <branchNameN> -m "message"
- 合并分支到當(dāng)前分支,自動進行新的提交:
- 查看分支合并情況:
git log --graph --pretty=oneline --abbrev-commit
#合并分支到當(dāng)前分支,首先我們在branchtest分支新建一個文件branchtest.txt,內(nèi)容為branchtest,然后提交;再l s切換到master分支,進行合并,會發(fā)現(xiàn)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
mergetool
????用于運行合并沖突解決工具來解決合并沖突。
- 摘要
git mergetool [--tool=<tool>] [-y | --[no-]prompt] [<file>…?]
- 概述
????git mergetool
命令用于運行合并沖突解決工具來解決合并沖突。使用git mergetool
運行合并實用程序來解決合并沖突。它通常在git合并后運行。
????如果給出一個或多個<file>
參數(shù),則將運行合并工具程序來解決每個文件的差異(跳過那些沒有沖突的文件)。 指定目錄將包括該路徑中的所有未解析文件。 如果沒有指定<file>
名稱,git mergetool
將在具有合并沖突的每個文件上運行合并工具程序。
- 示例
#首先我們分別進入branchtest 和branchtest2 分支,然后修改branchtest.txt文件內(nèi)容,并提交。然后切換到master分支,把這兩個分支合并到master,就會發(fā)現(xiàn)有沖突,然后我們用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):
#我們輸入文件名稱,然后可以看到文件的沖突,我們修改完沖突后保存再提交。
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>
- 概述
????當(dāng)要記錄工作目錄和索引的當(dāng)前狀態(tài),但想要返回到干凈的工作目錄時,則使用git stash
。 該命令保存本地修改,并恢復(fù)工作目錄以匹配HEAD提交。
????這個命令所儲藏的修改可以使用git stash list
列出,使用git stash show
進行檢查,并使用git stash apply
恢復(fù)(可能在不同的提交之上)。調(diào)用沒有任何參數(shù)的git stash
相當(dāng)于git stash save
。 默認(rèn)情況下,儲藏列表為“分支名稱上的WIP”,但您可以在創(chuàng)建一個消息時在命令行上給出更具描述性的消息。
- 示例
- 把當(dāng)前工作現(xiàn)場“儲藏”起來:
git stash
- 查看現(xiàn)有的儲藏:
git stash list
- 恢復(fù)工作區(qū):
git stash apply(恢復(fù))
andgit stash drop(刪除stash內(nèi)容)
orgit stash pop(恢復(fù)并刪除stash內(nèi)容)
- 把當(dāng)前工作現(xiàn)場“儲藏”起來:
$ 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)
標(biāo)簽管理
git tag
????用于創(chuàng)建,列出,刪除或驗證使用GPG簽名的標(biāo)簽對象。同大多數(shù) VCS 一樣,Git 也可以對某一時間點上的版本打上標(biāo)簽。在發(fā)布某個軟件版本(比如 v1.0 等等)的時候,經(jīng)常這么做。
- 摘要
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/中添加標(biāo)簽引用,除此之外還可以提供了-d/-l/-v
來刪除,列出或驗證標(biāo)簽。
????tag 用于創(chuàng)建一個標(biāo)簽用于在開發(fā)階段,某個階段的完成,創(chuàng)建一個版本,在開發(fā)中都會使用到, 可以創(chuàng)建一個tag來指向軟件開發(fā)中的一個關(guān)鍵時期,比如版本號更新的時候可以建一個version1.0, version1.2之類的標(biāo)簽,這樣在以后回顧的時候會比較方便。除非指定-f選項,否則不能創(chuàng)建已經(jīng)存在的標(biāo)簽。
????如果傳遞了-a
,-s
或-u <keyid>
中的一個,該命令將創(chuàng)建一個標(biāo)簽對象,并且需要一個標(biāo)簽消息。 除非-m <msg>
或-F <file>
,否則將啟動一個編輯器,供用戶輸入標(biāo)簽消息。
- 示例
- 創(chuàng)建標(biāo)簽(默認(rèn)為HEAD,也可以指定一個commit id):
git tag <tagName>
orgit tag -a <tagName> -m "標(biāo)簽說明"
orgit tag <tagName> <commitId>
- 列顯已有的標(biāo)簽:
git tag
orgit tag -l <tagName>(列出指定的標(biāo)簽)
- 刪除標(biāo)簽:
git tag -d <tagName>
- 創(chuàng)建標(biāo)簽(默認(rèn)為HEAD,也可以指定一個commit id):
#新建標(biāo)簽
$ git tag -a v1.0.0 -m "first tag"
# 列出也有標(biāo)簽
$ git tag
v1.0.0
# git show 命令查看相應(yīng)標(biāo)簽的版本信息,并連同顯示打標(biāo)簽時的提交對象。
$ 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
#刪除標(biāo)簽
$ git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 37b4083)
????整理文章主要為了自己日后復(fù)習(xí)用,文章中可能會引用到別的博主的文章,如涉及到博主的版權(quán)問題,請博主聯(lián)系我。