前言
Git使用教程
Git是一個(gè)開源的分布式版本控制系統(tǒng),用于敏捷高效地處理任何或小或大的項(xiàng)目。?
Git是 Linus Torvalds 為了幫助管理 Linux 內(nèi)核開發(fā)而開發(fā)的一個(gè)開放源碼的版本控制軟件。?
Git與常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本庫的方式苍鲜,不必服務(wù)器端軟件支持。
GIT不僅僅是個(gè)版本控制系統(tǒng)玷犹,它也是個(gè)內(nèi)容管理系統(tǒng)(CMS),工作管理系統(tǒng)等混滔。?
如果你是一個(gè)具有使用SVN背景的人,你需要做一定的思想轉(zhuǎn)換歹颓,來適應(yīng)GIT提供的一些概念和特征坯屿。?
Git 與 SVN 區(qū)別點(diǎn):
GIT是分布式的,SVN不是:這是GIT和其它非分布式的版本控制系統(tǒng)巍扛,例如SVN领跛,CVS等,最核心的區(qū)別撤奸。
GIT把內(nèi)容按元數(shù)據(jù)方式存儲吠昭,而SVN是按文件:所有的資源控制系統(tǒng)都是把文件的元信息隱藏在一個(gè)類似.svn,.cvs等的文件夾里。
GIT分支和SVN的分支不同:分支在SVN中一點(diǎn)不特別胧瓜,就是版本庫中的另外的一個(gè)目錄矢棚。
GIT沒有一個(gè)全局的版本號,而SVN有:目前為止這是跟SVN相比GIT缺少的最大的一個(gè)特征府喳。
GIT的內(nèi)容完整性要優(yōu)于SVN:GIT的內(nèi)容存儲使用的是SHA-1哈希算法蒲肋。這能確保代碼內(nèi)容的完整性,確保在遇到磁盤故障和網(wǎng)絡(luò)問題時(shí)降低對版本庫的破壞钝满。
Git 提供了一個(gè)叫做 git config 的工具肉津,專門用來配置或讀取相應(yīng)的工作環(huán)境變量。?
這些環(huán)境變量舱沧,決定了 Git 在各個(gè)環(huán)節(jié)的具體工作方式和行為。這些變量可以存放在以下三個(gè)不同的地方:
/etc/gitconfig 文件:系統(tǒng)中對所有用戶都普遍適用的配置偶洋。若使用 git config 時(shí)用 –system 選項(xiàng)熟吏,讀寫的就是這個(gè)文件。?
~/.gitconfig 文件:用戶目錄下的配置文件只適用于該用戶。若使用 git config 時(shí)用 –global 選項(xiàng)牵寺,讀寫的就是這個(gè)文件悍引。?
當(dāng)前項(xiàng)目的 Git 目錄中的配置文件(也就是工作目錄中的 .git/config 文件):這里的配置僅僅針對當(dāng)前項(xiàng)目有效。每一個(gè)級別的配置都會覆蓋上層的相同配置帽氓,所以 .git/config 里的配置會覆蓋 /etc/gitconfig 中的同名變量趣斤。
在 Windows 系統(tǒng)上,Git 會找尋用戶主目錄下的 .gitconfig 文件黎休。主目錄即 $HOME 變量指定的目錄浓领,一般都是 C:\Documents and Settings\$USER。
此外势腮,Git 還會嘗試找尋 /etc/gitconfig 文件联贩,只不過看當(dāng)初 Git 裝在什么目錄,就以此作為根目錄來定位烙如。
1.用戶信息 git config user
配置個(gè)人的用戶名稱和電子郵件地址:
$ git config --global user.name"wyndam"$ git config --global user.email"only.night@qq.com"
如果用了–global選項(xiàng)死陆,那么更改的配置文件就是位于你用戶主目錄下的那個(gè)呀非,以后你所有的項(xiàng)目都會默認(rèn)使用這里配置的用戶信息。?
如果要在某個(gè)特定的項(xiàng)目中使用其他名字或者電郵祸泪,只要去掉–global選項(xiàng)重新配置即可,新的設(shè)定保存在當(dāng)前項(xiàng)目的 .git/config 文件里建芙。
設(shè)置Git默認(rèn)使用的文本編輯器, 一般可能會是 Vi 或者 Vim没隘。如果你有其他偏好,比如 Emacs 的話岁钓,可以重新設(shè)置:
$ git config --global core.editor emacs
還有一個(gè)比較常用的是升略,在解決合并沖突時(shí)使用哪種差異分析工具。比如要改用 vimdiff 的話:
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3屡限,tkdiff品嚣,meld,xxdiff钧大,emerge翰撑,vimdiff,gvimdiff啊央,ecmerge眶诈,和 opendiff 等合并工具的輸出信息。?
當(dāng)然瓜饥,你也可以指定使用自己開發(fā)的工具逝撬,具體怎么做可以參閱后面的章節(jié)。
要檢查已有的配置信息乓土,可以使用 git config –list 命令:
$ git config --listcore.symlinks=falsecore.autocrlf=truecolor.diff=autocolor.status=autocolor.branch=autocolor.interactive=truepack.packsizelimit=2ghelp.format=htmlhttp.sslcainfo=E:/Platform/Git/mingw32/ssl/certs/ca-bundle.crtdiff.astextplain.textconv=astextplainrebase.autosquash=truefilter.lfs.clean=git-lfs clean %ffilter.lfs.smudge=git-lfs smudge %ffilter.lfs.required=trueuser.name=Wyndamuser.email=only.night@qq.comcore.editor=subl
有時(shí)候會看到重復(fù)的變量名宪潮,那就說明它們來自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig)溯警,不過最終 Git 實(shí)際采用的是最后一個(gè)。?
這些配置我們也可以在 ~/.gitconfig 或 /etc/gitconfig 看到狡相,如下所示:
[filter"lfs"]? ? clean = git-lfs clean %f? ? smudge = git-lfs smudge %f? ? required =true[user]? ? name = Wyndam? ? email = only.night@qq.com[core]? ? editor = subl
也可以直接查閱某個(gè)環(huán)境變量的設(shè)定梯轻,只要把特定的名字跟在后面即可,像這樣:
$ git config user.email
only.night@qq.com
本章節(jié)我們將為大家介紹 Git 的工作流程尽棕。?
一般工作流程如下:?
1. 克隆 Git 資源作為工作目錄喳挑。?
2. 在克隆的資源上添加或修改文件。?
3. 如果其他人修改了滔悉,你可以更新資源伊诵。?
4. 在提交前查看修改。?
5. 提交修改氧敢。?
6. 在修改完成后日戈,如果發(fā)現(xiàn)錯(cuò)誤,可以撤回提交并再次修改并提交孙乖。?
下圖展示了 Git 的工作流程:?
Git 工作區(qū)浙炼、暫存區(qū)和版本庫
我們先來理解下Git 工作區(qū)、暫存區(qū)和版本庫概念
工作區(qū):就是你項(xiàng)目的目錄(可見目錄)唯袄。
緩存區(qū):英文叫stage, 或index弯屈。一般存放在”git目錄”下的index文件(.git/index)中,所以我們把暫存區(qū)有時(shí)也叫作索引(index)恋拷。
版本庫:工作區(qū)有一個(gè)隱藏目錄.git资厉,這個(gè)不算工作區(qū),而是Git的版本庫蔬顾。
下面這個(gè)圖展示了工作區(qū)宴偿、版本庫中的暫存區(qū)和版本庫之間的關(guān)系:?
Git 創(chuàng)建倉庫
本章節(jié)我們將為大家介紹如何創(chuàng)建一個(gè) Git 倉庫。?
你可以使用一個(gè)已經(jīng)存在的目錄作為Git倉庫诀豁。
Git 使用 git init 命令來初始化一個(gè) Git 倉庫窄刘,Git 的很多命令都需要在 Git 的倉庫中運(yùn)行,所以 git init 是使用 Git 的第一個(gè)命令舷胜。?
在執(zhí)行完成 git init 命令后娩践,Git 倉庫會生成一個(gè) .git 目錄,該目錄包含了資源的所有元數(shù)據(jù)烹骨,其他的項(xiàng)目目錄保持不變(不像 SVN 會在每個(gè)子目錄生成 .svn 目錄翻伺,Git 只在倉庫的根目錄生成 .git 目錄)。
使用當(dāng)前目錄作為Git倉庫沮焕,我們只需使它初始化吨岭。
$ git init
該命令執(zhí)行完后會在當(dāng)前目錄生成一個(gè) .git 目錄。?
使用我們指定目錄作為Git倉庫峦树。
$ git init newrepo
初始化后未妹,會在 newrepo 目錄下會出現(xiàn)一個(gè)名為 .git 的目錄簿废,所有 Git 需要的數(shù)據(jù)和資源都存放在這個(gè)目錄中。?
如果當(dāng)前目錄下有幾個(gè)文件想要納入版本控制络它,需要先用 git add 命令告訴 Git 開始對這些文件進(jìn)行跟蹤,然后提交:
$ git add *.java$ git add README.md$ git commit -m"inital commit"
以上命令將目錄下以 .java 結(jié)尾及 README.md 文件提交到倉庫中歪赢。
我們使用 git clone 從現(xiàn)有 Git 倉庫中拷貝項(xiàng)目(類似 svn checkout)化戳。?
克隆倉庫的命令格式為:
$ git clone <repo>
如果我們需要克隆到指定的目錄,可以使用以下命令格式:
$ git clone <repo> <directory>
參數(shù)說明:
repo:Git 倉庫埋凯。
directory:本地目錄点楼。
比如,要克隆 Ruby 語言的 Git 代碼倉庫 Grit白对,可以用下面的命令:
$ git clone git://github.com/schacon/grit.git
執(zhí)行該命令后掠廓,會在當(dāng)前目錄下創(chuàng)建一個(gè)名為grit的目錄,其中包含一個(gè) .git 的目錄甩恼,用于保存下載下來的所有版本記錄蟀瞧。?
如果要自己定義要新建的項(xiàng)目目錄名稱,可以在上面的命令末尾指定新的名字:
$ git clone git://github.com/schacon/grit.git mygrit
Git 的工作就是創(chuàng)建和保存你項(xiàng)目的快照及與之后的快照進(jìn)行對比条摸。本章將對有關(guān)創(chuàng)建與提交你的項(xiàng)目快照的命令作介紹悦污。
用 git init 在目錄中創(chuàng)建新的 Git 倉庫。 你可以在任何時(shí)候钉蒲、任何目錄中這么做切端,完全是本地化的。?
在目錄中執(zhí)行 git init顷啼,就可以創(chuàng)建一個(gè) Git 倉庫了踏枣。比如我們創(chuàng)建 runoob 項(xiàng)目:
$ mkdir wyndam$cdwyndam/$ git initInitialized empty Git repositoryinC:/Users/lion/Desktop/wyndam/.git/# 在 桌面/wyndam/ 目錄初始化空 Git 倉庫完畢。
現(xiàn)在你可以看到在你的項(xiàng)目中生成了 .git 這個(gè)子目錄钙蒙。 這就是你的 Git 倉庫了茵瀑,所有有關(guān)你的此項(xiàng)目的快照數(shù)據(jù)都存放在這里。
$ ls-a.? ..? .git
使用 git clone 拷貝一個(gè) Git 倉庫到本地仪搔,讓自己能夠查看該項(xiàng)目瘾婿,或者進(jìn)行修改。?
如果你需要與他人合作一個(gè)項(xiàng)目烤咧,或者想要復(fù)制一個(gè)項(xiàng)目偏陪,看看代碼,你就可以克隆那個(gè)項(xiàng)目煮嫌。 執(zhí)行命令:
$ git clone [url]
[url] 為你想要復(fù)制的項(xiàng)目git地址笛谦,就可以了。?
例如我們克隆 Github 上的項(xiàng)目:
$ git clone https://www.github.com/onlynight/Proxy.gitCloning into'Proxy'...remote: Counting objects:50, done.remote: Compressing objects:100% (28/28), done.remote: Total50(delta13), reused47(delta10), pack-reused0Unpacking objects:100% (50/50), done.Checking connectivity... done.
克隆完成后昌阿,在當(dāng)前目錄下會生成一個(gè) simplegit 目錄:
$cdProxy/$ ls-a.? ..? .git? .idea? Proxy.iml? README.md? images? src
默認(rèn)情況下饥脑,Git 會按照你提供的 URL 所指示的項(xiàng)目的名稱創(chuàng)建你的本地項(xiàng)目目錄恳邀。 通常就是該 URL 最后一個(gè) / 之后的項(xiàng)目名稱。如果你想要一個(gè)不一樣的名字灶轰, 你可以在該命令后加上你想要的名稱谣沸。
Git 的工作就是創(chuàng)建和保存你的項(xiàng)目的快照及與之后的快照進(jìn)行對比。本章將對有關(guān)創(chuàng)建與提交你的項(xiàng)目的快照的命令作介紹笋颤。
git add 命令可將該文件添加到緩存乳附,如我們添加以下兩個(gè)文件:
$ touch README.md$ touch HelloWorld.java$ lsHelloWorld.java? README.md$ git status-s?? HelloWorld.java?? README.md
git status 命令用于查看項(xiàng)目的當(dāng)前狀態(tài)。?
接下來我們執(zhí)行 git add 命令來添加文件:
$ git add README.md HelloWorld.java
現(xiàn)在我們再執(zhí)行 git status伴澄,就可以看到這兩個(gè)文件已經(jīng)加上去了赋除。
$ git status-sA? HelloWorld.javaA? README.md
新項(xiàng)目中,添加所有文件很普遍非凌,我們可以使用 git add . 命令來添加當(dāng)前項(xiàng)目的所有文件举农。?
現(xiàn)在我們修改 README 文件:
$ vim README#README.mdThis is readme markdown file.$ git status-sA? HelloWorld.javaAM README.md
“AM” 狀態(tài)的意思是,這個(gè)文件在我們將它添加到緩存之后又有改動敞嗡。改動后我們在執(zhí)行 git add 命令將其添加到緩存中:
$ git add .$ git status-sA? HelloWorld.javaA? README.md
當(dāng)你要將你的修改包含在即將提交的快照里的時(shí)候颁糟,需要執(zhí)行 git add。
git status 以查看在你上次提交之后是否有修改秸妥。?
我演示該命令的時(shí)候加了 -s 參數(shù)滚停,以獲得簡短的結(jié)果輸出。如果沒加該參數(shù)會詳細(xì)輸出內(nèi)容:
$ git statusOn branch masterInitial commitChanges to be committed:? (use"git rm --cached <file>..."to unstage)? ? ? ? new file:? HelloWorld.java? ? ? ? new file:? README.md
執(zhí)行 git diff 來查看執(zhí)行 git status 的結(jié)果的詳細(xì)信息粥惧。?
git diff 命令顯示已寫入緩存與已修改但尚未寫入緩存的改動的區(qū)別键畴。git diff 有兩個(gè)主要的應(yīng)用場景。
尚未緩存的改動:git diff
查看已緩存的改動: git diff –cached
查看已緩存的與未緩存的所有改動:git diff HEAD
顯示摘要而非整個(gè) diff:git diff –stat
在 HelloWorld.java 文件中輸入以下內(nèi)容:
publicclassHelloWorld{publicstaticvoidmain(String[] args) {? ? ? ? System.out.println("Hello World!");? ? }}
$ git status -sAM HelloWorld.javaA? README.md$ git diffdiff --git a/HelloWorld.java b/HelloWorld.javaindex e69de29..68271e5100644--- a/HelloWorld.java+++ b/HelloWorld.java@@ -0,0+1,7@@+publicclassHelloWorld{++publicstaticvoidmain(String[] args) {+? ? ? ? ? ? ? System.out.println("Hello World!");+? ? ? }++}
git status 顯示你上次提交更新后的更改或者寫入緩存的改動突雪, 而 git diff 一行一行地顯示這些改動具體是啥起惕。?
接下來我們來查看下 git diff –cached 的執(zhí)行效果:
$ git add HelloWorld.java$ git status -sA? HelloWorld.javaA? README.md$ git diff --cacheddiff --git a/HelloWorld.java b/HelloWorld.javanew file mode 100644index 0000000..68271e5--- /dev/null+++ b/HelloWorld.java@@ -0,0 +1,7 @@+public class HelloWorld {++? ? ? public static void main(String[] args) {+? ? ? ? ? ? ? System.out.println("Hello World!");+? ? ? }++}diff --git a/README.md b/README.mdnew file mode 100644index 0000000..8123762--- /dev/null+++ b/README.md@@ -0,0 +1,3 @@+#README.md++This is readme markdown file.
使用 git add 命令將想要快照的內(nèi)容寫入緩存區(qū), 而執(zhí)行 git commit 將緩存區(qū)內(nèi)容添加到倉庫中咏删。?
Git 為你的每一個(gè)提交都記錄你的名字與電子郵箱地址惹想,所以第一步需要配置用戶名和郵箱地址。
$ git config --golbal user.name'wyndam'$ git config --golbal user.email'only.night@qq.com'
接下來我們寫入緩存督函,并提交對 hello.php 的所有改動嘀粱。在首個(gè)例子中,我們使用 -m 選項(xiàng)以在命令行中提供提交注釋辰狡。
$ git add README.md$ git add HelloWorld.java$ git status-sA? HelloWorld.javaA? README.md$ git commit -m'inital commit'[master (root-commit) fdd5c53] inital commit2files changed,10insertions(+) create mode100644HelloWorld.java create mode100644README.md
現(xiàn)在我們已經(jīng)記錄了快照锋叨。如果我們再執(zhí)行 git status:
$ git status
On branch master
nothing to commit, working directory clean
以上輸出說明我們在最近一次提交之后,沒有做任何改動宛篇,是一個(gè)”working directory clean:干凈的工作目錄”娃磺。?
如果你沒有設(shè)置 -m 選項(xiàng),Git 會嘗試為你打開一個(gè)編輯器以填寫提交信息叫倍。 如果 Git 在你對它的配置中找不到相關(guān)信息偷卧,默認(rèn)會打開 vim豺瘤。屏幕會像這樣:
# Please enter the commit message for your changes. Lines starting# with '#' will be ignored, and an empty message aborts the commit.# On branch master# Changes to be committed:#? (use "git reset HEAD <file>..." to unstage)## modified:? HelloWorld.java#~~".git/COMMIT_EDITMSG"9L,257C
如果你覺得 git add 提交緩存的流程太過繁瑣,Git 也允許你用 -a 選項(xiàng)跳過這一步听诸。命令格式如下:
$ git commit-a
我們先修改 HelloWorld.java 文件為以下內(nèi)容:
publicclassHelloWorld{publicstaticvoidmain(String[] args) {? ? ? ? System.out.println("Hello World!!!");? ? }}
再執(zhí)行以下命令:
$ git commit -am"修改HelloWorld.java文件"[master c2c167c] 修改HelloWorld.java文件1file changed,1insertion(+),1deletion(-)
git reset HEAD 命令用于取消已緩存的內(nèi)容坐求。?
我們先改動文件 README 文件,內(nèi)容如下:
#README.md##This is readme markdown file
HelloWorld.java 文件修改為:
publicclassHelloWorld{publicstaticvoidmain(String[] args) {? ? ? ? System.out.println("Hello World!");? ? }}
現(xiàn)在兩個(gè)文件修改后蛇更,都提交到了緩存區(qū)瞻赶,我們現(xiàn)在要取消其中一個(gè)的緩存,操作如下:
$ git status-sM HelloWorld.java M README.md$ git add .$ git status-sM? HelloWorld.javaM? README.md$ git reset HEAD -- HelloWorld.javaUnstaged changes after reset:M? ? ? HelloWorld.java$ git status-sM HelloWorld.javaM? README.md
現(xiàn)在你執(zhí)行 git commit派任,只會將 README.md 文件的改動提交,而 HelloWorld.java 是沒有的璧南。
$ git commit -m"修改"[master ad5f6fe] 修改1file changed,1insertion(+),1deletion(-)$ git status-sM HelloWorld.java
可以看到 HelloWorld.java 文件的修改并為提交掌逛。?
這時(shí)我們可以使用以下命令將 HelloWorld.java 的修改提交:
$ git commit -am"修改 HelloWorld.java 文件"[master a055c08] 修改 HelloWorld.java 文件1file changed,1insertion(+),1deletion(-)$ git statusOn branch masternothing to commit, working directory clean
簡而言之,執(zhí)行 git reset HEAD 以取消之前 git add 添加司倚,但不希望包含在下一提交快照中的緩存豆混。
git rm 會將條目從緩存區(qū)中移除。這與 git reset HEAD 將條目取消緩存是有區(qū)別的动知。 “取消緩存”的意思就是將緩存區(qū)恢復(fù)為我們做出修改之前的樣子皿伺。?
默認(rèn)情況下,git rm file 會將文件從緩存區(qū)和你的硬盤中(工作目錄)刪除盒粮。?
如果你要在工作目錄中留著該文件鸵鸥,可以使用 git rm –cached:?
如我們刪除 hello.php文件:
$ git rm HelloWorld.javarm'HelloWorld.java'$ lsREADME.md
不從工作區(qū)中刪除文件:
$ git rm README.md --cachedrm'README.md'$ lsREADME.md
git mv 命令做得所有事情就是 git rm –cached 命令的操作, 重命名磁盤上的文件丹皱,然后再執(zhí)行 git add 把新文件添加到緩存區(qū)妒穴。?
我們先把剛移除的 README 添加回來:
$ git add README.md
然后對其重名:
$ git mv README.md README
$ ls
README
幾乎每一種版本控制系統(tǒng)都以某種形式支持分支。使用分支意味著你可以從開發(fā)主線上分離開來摊崭,然后在不影響主線的同時(shí)繼續(xù)工作讼油。?
有人把 Git 的分支模型稱為”必殺技特性”,而正是因?yàn)樗佤ぃ瑢?Git 從版本控制系統(tǒng)家族里區(qū)分出來矮台。?
創(chuàng)建分支命令:
git branch [branch name]
切換分支命令:
git checkout [branch name]
當(dāng)你切換分支的時(shí)候,Git 會用該分支的最后提交的快照替換你的工作目錄的內(nèi)容根时, 所以多個(gè)分支不需要多個(gè)目錄瘦赫。?
合并分支命令:
git merge
你可以多次合并到統(tǒng)一分支, 也可以選擇在合并之后直接刪除被并入的分支啸箫。
列出分支 git branch
列出分支基本命令:
git branch
沒有參數(shù)時(shí)耸彪,git branch 會列出你在本地的分支。
$ git branch
* master
1
2
此例的意思就是忘苛,我們有一個(gè)叫做”master”的分支蝉娜,并且該分支是當(dāng)前分支唱较。?
當(dāng)你執(zhí)行 git init 的時(shí)候,缺省情況下 Git 就會為你創(chuàng)建”master”分支召川。?
如果我們要手動創(chuàng)建一個(gè)分支南缓,并切換過去。執(zhí)行 git branch (branchname) 即可荧呐。
$ git branch testing
$ git branch
* master
? testing
現(xiàn)在我們可以看到汉形,有了一個(gè)新分支 testing。?
當(dāng)你以此方式在上次提交更新之后創(chuàng)建了新分支倍阐,如果后來又有更新提交概疆, 然后又切換到了”testing”分支,Git 將還原你的工作目錄到你創(chuàng)建分支時(shí)候的樣子?
接下來我們將演示如何切換分支峰搪,我們用 git checkout (branch) 切換到我們要修改的分支岔冀。
$ lsREADME$echo'w3cschool.cc'> test.txt$ git add .$ git commit -m'add test.txt'[master048598f] add test.txt2files changed,1insertion(+),3deletions(-) delete mode100644hello.php create mode100644test.txt$ lsREADME? ? ? test.txt$ git checkout testingSwitched to branch'testing'$ lsREADME.md? ? ? HelloWorld.java
當(dāng)我們切換到”testing”分支的時(shí)候,我們添加的新文件test.txt被移除了, 原來被刪除的文件hello.php文件又出現(xiàn)了概耻。切換回”master”分支的時(shí)候使套,它們有重新出現(xiàn)了。
$ git checkout masterSwitched to branch'master'$ lsREADME? ? ? test.txt
首先我們在master分支中在添加一個(gè)新文件test2.txt:
$ touch test2.txt$ git add test2.txt$ git commit -m'add test2.txt'$ lsREADME? test.txt? test2.txt
我們也可以使用 git checkout -b (branchname) 命令來創(chuàng)建新分支并立即切換到該分支下鞠柄,從而在該分支中操作侦高。
$ git checkout -b newtestSwitched to a new branch'newtest'$ git rm test2.txt rm'test2.txt'$ lsREADME? ? ? test.txt$ git commit -am'removed test2.txt'[newtest556f0a0] removed test2.txt1file changed,1deletion(-) delete mode100644test2.txt$ git checkout masterSwitched to branch'master'$ lsREADME? ? ? test.txt? ? test2.txt
如你所見,我們創(chuàng)建了一個(gè)分支厌杜,在該分支的上下文中移除了一些文件奉呛,然后切換回我們的主分支,那些文件又回來了期奔。?
使用分支將工作切分開來侧馅,從而讓我們能夠在不同上下文中做事,并來回切換呐萌。
刪除分支命令:
git branch-d[branch name]
例如我們要刪除”testing”分支:
$ git branch* master? newtest? testing$ git branch -D testingDeleted branch testing (was84b13b9).$ git branch* master? newtest
一旦某分支有了獨(dú)立內(nèi)容馁痴,你終究會希望將它合并回到你的主分支。 你可以使用以下命令將任何分支合并到當(dāng)前分支中去:
git merge
$ git branch* master? newtest$ lsREADME? ? ? test.txt? ? test2.txt$ git merge newtestUpdating a055c08..202199dFast-forward HelloWorld.java? ? |7------- README.md => README |0test.txt? ? ? ? ? ? |1+3files changed,1insertion(+),7deletions(-) delete mode100644HelloWorld.java rename README.md => README (100%) create mode100644test.txt$ lsREADME? test.txt
以上實(shí)例中我們將 newtest 分支合并到主分支去肺孤,test2.txt 文件被刪除罗晕。
合并并不僅僅是簡單的文件添加、移除的操作赠堵,Git 也會合并修改小渊。
$ git branch
* master
? newtest
$ cat test.txt
w3cschool.cc
首先,我們創(chuàng)建一個(gè)叫做”change_site”的分支茫叭,切換過去酬屉,我們將內(nèi)容改為 www.w3cschool.cc 。
$ git checkout -b change_siteSwitched to a new branch'change_site'$ vim test.txt $ head -1test.txt www.w3cschool.cc$ git commit -am'changed the site'[change_site d7e7346] changed the site1file changed,1insertion(+),1deletion(-)
將修改的內(nèi)容提交到 “change_site” 分支中。 現(xiàn)在呐萨,假如切換回 “master” 分支我們可以看內(nèi)容恢復(fù)到我們修改前的杀饵,我們再次修改test.txt文件。
$ git checkout masterSwitched to branch'master'$ head -1test.txt w3cschool.cc$ vim test.txt $ cat test.txtw3cschool.cc新增加一行$ git diffdiff --git a/test.txt b/test.txtindex704cce7..f84c2a4100644--- a/test.txt+++ b/test.txt@@ -1+1,2@@ w3cschool.cc+新增加一行$ git commit -am'新增加一行'[master14b4dca] 新增加一行1file changed,1insertion(+)
現(xiàn)在這些改變已經(jīng)記錄到我的 “master” 分支了谬擦。接下來我們將 “change_site” 分支合并過來切距。
$ git merge change_siteAuto-merging test.txtCONFLICT (content): Merge conflictintest.txtAutomatic merge failed; fix conflicts andthencommit the result.$ cat test.txt <<<<<<< HEADw3cschool.cc新增加一行=======www.w3cschool.cc>>>>>>> change_site
我們將前一個(gè)分支合并到 “master” 分支,一個(gè)合并沖突就出現(xiàn)了惨远,接下來我們需要手動去修改它谜悟。
$ vim test.txt $ cat test.txt www.w3cschool.cc新增加一行$ git diffdiff --cc test.txtindex f84c2a4,bccb7c2..0000000--- a/test.txt+++ b/test.txt@@@ -1,2-1,1+1,2@@@- w3cschool.cc+ www.w3cschool.cc +新增加一行
在 Git 中,我們可以用 git add 要告訴 Git 文件沖突已經(jīng)解決
$ git status-sUU test.txt$ git add test.txt $ git status-sM? test.txt$ git commit[master88afe0e] Merge branch'change_site'
在使用 Git 提交了若干更新之后北秽,又或者克隆了某個(gè)項(xiàng)目葡幸,想回顧下提交歷史,我們可以使用 git log 命令查看贺氓。?
針對我們前一章節(jié)的操作礼患,使用 git log 命令列出歷史提交記錄如下:
$ git logcommit2b5970dc2a936649791afc8cedb6dbaee46d2176Merge: e2714c9 d17a0a0Author: Wyndam Date:? Thu Oct2017:00:572016+0800Merge branch'change_site'commit e2714c9ecf376efefc8d149ac219a6e98c80790bAuthor: Wyndam Date:? Thu Oct2016:58:092016+0800新增加一行commit d17a0a0065e1e1d1c1078cfabf18f2c8491f0b7cAuthor: Wyndam Date:? Thu Oct2016:54:132016+0800change the sitecommit202199d023f307e74229e46ee90fc351d2e6d4f6Author: Wyndam Date:? Thu Oct2015:50:552016+0800add test.txt filecommit a055c0816bc94a9abe21ffe4a4014851943ea139Author: Wyndam Date:? Thu Oct2015:35:502016+0800修改 HelloWorld.java 文件commit ad5f6fe0474c52c464e94cd41faf45e705445847Author: Wyndam Date:? Thu Oct2015:34:162016+0800修改commit c2c167c36533768be8fc91e4cb3ba0b7d328a074Author: Wyndam Date:? Thu Oct2015:24:412016+0800修改HelloWorld.java文件commit f9393bf0e7f701248b56c97827a9d101e74b3952Author: Wyndam Date:? Thu Oct2015:21:022016+0800third commit? ? ``commit316fafcf38bb2eb600f4226345ea09a4e37d9ec4Author: Wyndam Date:? Thu Oct2015:18:582016+0800second commitcommit fdd5c53457270c10a163a0cf3fcfd9027e6e1ecbAuthor: Wyndam Date:? Thu Oct2015:10:432016+0800inital commit
我們可以用 –oneline 選項(xiàng)來查看歷史記錄的簡潔的版本。
$ git log --oneline2b5970d Merge branch'change_site'e2714c9 新增加一行d17a0a0 change the site202199d add test.txt filea055c08 修改 HelloWorld.java 文件ad5f6fe 修改c2c167c 修改HelloWorld.java文件f9393bf third commit ``316fafc second commitfdd5c53 inital commit
這告訴我們的是掠归,此項(xiàng)目的開發(fā)歷史。?
我們還可以用 –graph 選項(xiàng)悄泥,查看歷史中什么時(shí)候出現(xiàn)了分支虏冻、合并。以下為相同的命令弹囚,開啟了拓?fù)鋱D選項(xiàng):
$ git log --oneline --graph*2b5970d Merge branch'change_site'|\| * d17a0a0 change the site* | e2714c9 新增加一行|/*202199d add test.txt file* a055c08 修改 HelloWorld.java 文件* ad5f6fe 修改* c2c167c 修改HelloWorld.java文件* f9393bf third commit ``*316fafc second commit* fdd5c53 inital commit
現(xiàn)在我們可以更清楚明了地看到何時(shí)工作分叉厨相、又何時(shí)歸并。?
你也可以用 ‘–reverse’參數(shù)來逆向顯示所有日志鸥鹉。
$ git log --oneline --reversefdd5c53 inital commit316fafc second commitf9393bf third commit ``c2c167c 修改HelloWorld.java文件ad5f6fe 修改a055c08 修改 HelloWorld.java 文件202199d add test.txt filed17a0a0 change the sitee2714c9 新增加一行2b5970d Merge branch'change_site'
如果只想查找指定用戶的提交日志可以使用命令:git log –author , 例如蛮穿,比方說我們要找 Git 源碼中 Linus 提交的部分:
$ git log --author=Linus --oneline -581b50f3 Move'builtin-*'into a'builtin/'subdirectory3bb7256 make"index-pack"a built-in377d027 make"git pack-redundant"a built-inb532581 make"git unpack-file"a built-in112dd51 make"mktag"a built-in
如果你要指定日期,可以執(zhí)行幾個(gè)選項(xiàng):–since 和 –before毁渗,但是你也可以用 –until 和 –after践磅。?
例如,如果我要看 Git 項(xiàng)目中三周前且在四月十八日之后的所有提交灸异,我可以執(zhí)行這個(gè)(我還用了 –no-merges 選項(xiàng)以隱藏合并提交):
$ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges5469e2d Git1.7.1-rc2d43427d Documentation/remote-helpers: Fix typos and improve language272a36b Fixup: Second argument may be any arbitrary stringb6c8d2d Documentation/remote-helpers: Add invocation section5ce4f4e Documentation/urls: Rewrite to accomodate transport::address00b84e9 Documentation/remote-helpers: Rewrite description03aa87e Documentation: Describe other situations where -z affects git diff77bc694 rebase-interactive: silence warning when no commits rewritten636db2c t3301: add tests to use --format="%N"
如果你達(dá)到一個(gè)重要的階段府适,并希望永遠(yuǎn)記住那個(gè)特別的提交快照,你可以使用 git tag 給它打上標(biāo)簽肺樟。?
比如說檐春,我們想為我們的 w3cschoolcc 項(xiàng)目發(fā)布一個(gè)”1.0”版本。 我們可以用 git tag -a v1.0 命令給最新一次提交打上(HEAD)”v1.0”的標(biāo)簽么伯。?
-a 選項(xiàng)意為”創(chuàng)建一個(gè)帶注解的標(biāo)簽”疟暖。 不用 -a 選項(xiàng)也可以執(zhí)行的,但它不會記錄這標(biāo)簽是啥時(shí)候打的,誰打的俐巴,也不會讓你添加個(gè)標(biāo)簽的注解骨望。 我推薦一直創(chuàng)建帶注解的標(biāo)簽。
$ git tag-av1.0
當(dāng)你執(zhí)行 git tag -a 命令時(shí)窜骄,Git 會打開你的編輯器锦募,讓你寫一句標(biāo)簽注解,就像你給提交寫注解一樣邻遏。?
現(xiàn)在糠亩,注意當(dāng)我們執(zhí)行 git log –decorate 時(shí),我們可以看到我們的標(biāo)簽了:
$ git log --oneline --graph --decorate*2b5970d (HEAD -> master, tag: v1.0) Merge branch'change_site'|\| * d17a0a0 (change_site) change the site* | e2714c9 新增加一行|/*202199d (newtest) add test.txt file* a055c08 修改 HelloWorld.java 文件* ad5f6fe 修改* c2c167c 修改HelloWorld.java文件* f9393bf third commit ``*316fafc second commit* fdd5c53 inital commit
如果我們忘了給某個(gè)提交打標(biāo)簽准验,又將它發(fā)布了赎线,我們可以給它追加標(biāo)簽。?
例如糊饱,假設(shè)我們發(fā)布了提交 85fc7e7(上面實(shí)例最后一行)垂寥,但是那時(shí)候忘了給它打標(biāo)簽。 我們現(xiàn)在也可以:
$ git tag-av0.9a055c08$ git log --oneline --graph --decorate*2b5970d (HEAD -> master, tag: v1.0) Merge branch'change_site'|\| * d17a0a0 (change_site) change the site* | e2714c9 新增加一行|/*202199d (newtest) add test.txt file* a055c08 (tag: v0.9) 修改 HelloWorld.java 文件* ad5f6fe 修改* c2c167c 修改HelloWorld.java文件* f9393bf third commit ``*316fafc second commit* fdd5c53 inital commit
如果我們要查看所有標(biāo)簽可以使用以下命令:
$ git tagv0.9v1.0
指定標(biāo)簽信息命令:
git tag-a -m"w3cschool.cc標(biāo)簽"
PGP簽名標(biāo)簽命令:
git tag-s -m"w3cschool.cc標(biāo)簽"
Git 并不像 SVN 那樣有個(gè)中心服務(wù)器另锋。?
目前我們使用到的 Git 命令都是在本地執(zhí)行滞项,如果你想通過 Git 分享你的代碼或者與其他開發(fā)人員合作。 你就需要將數(shù)據(jù)放到一臺其他開發(fā)人員能夠連接的服務(wù)器上夭坪。
要添加一個(gè)新的遠(yuǎn)程倉庫文判,可以指定一個(gè)簡單的名字,以便將來引用,命令格式如下:
git remote add [shortname] [url]
本例以Github為例作為遠(yuǎn)程倉庫室梅,如果你沒有Github可以在官網(wǎng)https://github.com/注冊戏仓。?
由于你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以我們需要配置驗(yàn)證信息:?
使用以下命令生成SSH Key:
$ ssh-keygen -t rsa -C"youremail@example.com"
后面的your_email@youremail.com改為你在github上注冊的郵箱亡鼠,之后會要求確認(rèn)路徑和輸入密碼赏殃,我們這使用默認(rèn)的一路回車就行。成功的話會在~/下生成.ssh文件夾间涵,進(jìn)去仁热,打開id_rsa.pub,復(fù)制里面的key浑厚。?
回到github上股耽,進(jìn)入 Account Settings(賬戶配置),左邊選擇SSH Keys钳幅,Add SSH Key,title隨便填物蝙,粘貼在你電腦上生成的key。
為了驗(yàn)證是否成功敢艰,輸入以下命令:
$ ssh -T git@github.comHi onlynight! You'vesuccessfully authenticated, but GitHub doesnotprovide shellaccess.
輸出以上結(jié)果證明已經(jīng)正確配置密鑰诬乞。
之后登錄后點(diǎn)擊” New repository ” 如下圖所示
之后在在Repository name 填入 GitAdd(遠(yuǎn)程倉庫名) ,description中填寫描述”git add test”,其他保持默認(rèn)設(shè)置震嫉,點(diǎn)擊”Create repository”按鈕森瘪,就成功地創(chuàng)建了一個(gè)新的Git倉庫:
創(chuàng)建成功后,顯示如下信息:
以上信息告訴我們可以從這個(gè)倉庫克隆出新的倉庫票堵,也可以把本地倉庫的內(nèi)容推送到GitHub倉庫扼睬。?
現(xiàn)在,我們根據(jù)GitHub的提示悴势,在本地的倉庫下運(yùn)行命令:
$ lsREADME? test.txt$ git remote add origin git@github.com:onlynight/GitAdd.git$ git push -u origin masterCounting objects:26, done.Delta compression using up to4threads.Compressing objects:100% (20/20), done.Writing objects:100% (26/26),2.44KiB |0bytes/s, done.Total26(delta4), reused0(delta0)remote: Resolving deltas:100% (4/4), done.To git@github.com:onlynight/GitAdd.git * [new branch]? ? ? master -> masterBranch mastersetup to track remote branch master from origin.
查看當(dāng)前的遠(yuǎn)程庫 git remote
要查看當(dāng)前配置有哪些遠(yuǎn)程倉庫窗宇,可以用命令:
git remote
$ git remote
origin
$ git remote -v
執(zhí)行時(shí)加上 -v 參數(shù),你還可以看到每個(gè)別名的實(shí)際鏈接地址特纤。
Git 有兩個(gè)命令用來提取遠(yuǎn)程倉庫的更新军俊。
1. 從遠(yuǎn)程倉庫下載新分支與數(shù)據(jù): git fetch
git fetch
該命令執(zhí)行完后需要執(zhí)行g(shù)it merge 遠(yuǎn)程分支到你所在的分支。
2. 從遠(yuǎn)端倉庫提取數(shù)據(jù)并嘗試合并到當(dāng)前分支: git pull
git pull
該命令就是在執(zhí)行 git fetch 之后緊接著執(zhí)行 git merge 遠(yuǎn)程分支到你所在的任意分支捧存。?
假設(shè)你配置好了一個(gè)遠(yuǎn)程倉庫粪躬,并且你想要提取更新的數(shù)據(jù),你可以首先執(zhí)行 git fetch [alias] 告訴 Git 去獲取它有你沒有的數(shù)據(jù)昔穴,然后你可以執(zhí)行 git merge [alias]/[branch] 以將服務(wù)器上的任何更新(假設(shè)有人這時(shí)候推送到服務(wù)器了)合并到你的當(dāng)前分支镰官。
接下來我們在 Github 上點(diǎn)擊”test.txt” 并在線修改它。之后我們在本地更新修改吗货。
$ git fetch originremote: Counting objects:3, done.remote: Compressing objects:100% (3/3), done.remote: Total3(delta0), reused0(delta0), pack-reused0Unpacking objects:100% (3/3), done.From github.com:onlynight/GitAdd774112b..37be49b? master? ? -> origin/master
以上信息”774112b..37be49b master -> origin/master” 說明 master 分支已被更新朋魔,我們可以使用以下命令將更新同步到本地:
$ git merge origin/masterUpdating774112b..37be49bFast-forward test.txt |1+1file changed,1insertion(+)
推送你的新分支與數(shù)據(jù)到某個(gè)遠(yuǎn)端倉庫命令:
git push [alias] [branch]
以上命令將你的 [branch] 分支推送成為 [alias] 遠(yuǎn)程倉庫上的 [branch] 分支,實(shí)例如下卿操。
$ git push origin master
Everything up-to-date
注意:如果要刪除遠(yuǎn)程分支同樣也是使用push命令,在分支前加上”:”表示刪除遠(yuǎn)程分支孙援,代碼如下:
$ git push origin :<branch name>
刪除本地倉庫的遠(yuǎn)程倉庫鏈接 git remote rm
刪除遠(yuǎn)程倉庫你可以使用命令:
git remote rm [alias]
$ git remote -v
origin? git@github.com:onlynight/GitAdd.git (fetch)
origin? git@github.com:onlynight/GitAdd.git (push)
$ git remote -v
origin? git@github.com:onlynight/GitAdd.git (fetch)
origin? git@github.com:onlynight/GitAdd.git (push)
origin2 git@github.com:onlnynight/GitAdd.git (fetch)
origin2 git@github.com:onlnynight/GitAdd.git (push)
$ git remote rm origin2
$ git remote -v
origin? git@github.com:onlynight/GitAdd.git (fetch)
origin? git@github.com:onlynight/GitAdd.git (push)