前言java
因爲最近公司開始中止使用SVN,開始轉向GIT了,利用週末的時間學習實踐了下,分享給你們~git
什麼是Git?程序員
Git的官網是:http://git-scm.com/ ,咱們能夠在上面瞭解到GIT的一些介紹:github Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git是一個開源的,免費的,分佈式的版本管理系統。apache 咱們知道CVS,SVN,也是經常使用的版本管理系統,他們之間最大的區別在於「分佈式」。bash 另外,咱們還須要注意GIT的一個特性:everything is local 服務器 要知道CSV,SVN,咱們本地安裝的是客戶端,必須經過網絡鏈接到服務器,才能取得代碼,若是斷網,那就OVER了。可是GIT則不一樣,它全部的東西都在本地存放,也就是說在斷網的狀況下,能夠離線運行。網絡 說到GIT,那麼天然要知道一個網站:https://github.com/ 這是一個著名的程序員社交網站,咱們能夠在GITHUB上發佈本身的項目或者參與到別人的項目中。分佈式 GIT是大名鼎鼎的LINUX之父在2005年發佈,通過多年的沉澱,在開源社區使用率很是普遍,能夠說花一點時間學習GIT,將會給咱們帶來巨大的幫助,那麼下面咱們就開始吧! |
來,安裝Git!
目前GIT的最新版本是2.6.3,GIT雖然有GUI,可是經過命令行的方式纔是掌握GIT的最佳方式,所以我將使用LINUX GIT來進行實踐。 爲了不安裝GIT的過程當中,涉及到諸多依賴,我已經在LINUX作好YUM源,並安裝了一些經常使用工具包,以下所示。 [root@localhost ~]# yum grouplist install Loading "rhnplugin" plugin Loading "security" plugin Loading "installonlyn" plugin This system is not registered with RHN. RHN support will be disabled. Setting up Group Process Setting up repositories Installed Groups: Office/Productivity MySQL Database Development Libraries System Tools GNOME Desktop Environment Network Servers X Window System Printing Support Mail Server Server Configuration Tools Administration Tools Graphical Internet 你們能夠到https://www.kernel.org/pub/software/scm/git/ 下載 git-2.6.3.tar.gz tar -xvf git-2.6.3.tar.gz ./configure --prefix=/usr/local make make install 安裝完畢後,咱們能夠看到: [root@localhost bin]# pwd /usr/local/bin [root@localhost bin]# ll total 23260 -rwxr-xr-x 116 root root 5817589 Dec 4 18:29 git -rwxr-xr-x 2 root root 162431 Dec 4 18:29 git-cvsserver -rwxr-xr-x 1 root root 348074 Dec 4 18:29 gitk -rwxr-xr-x 116 root root 5817589 Dec 4 18:29 git-receive-pack -rwxr-xr-x 2 root root 2763905 Dec 4 18:29 git-shell -rwxr-xr-x 116 root root 5817589 Dec 4 18:29 git-upload-archive -rwxr-xr-x 2 root root 2998205 Dec 4 18:29 git-upload-pack [root@localhost /]# git --version git version 2.6.3 [root@localhost /]# |
要使用,就要先配置Git
配置GIT,很簡單! [root@localhost /]# git config --global user.name zhangfengzhe [root@localhost /]# git config --global user.email zhangfengzhe1990@163.com [root@localhost /]# git config --global color.ui true 之因此要配置USERNAME/EMAIL就是說對代碼的改動進行惟一PERSON標示 爲了讓GIT有些色彩,咱們對顏色進行了配置。 列出配置: [root@localhost /]# git config --list user.name=zhangfengzhe user.email=zhangfengzhe1990@163.com color.ui=true [root@localhost /]# 說白了,咱們利用git config命令進行的配置操做,其實是對文件的改動,那麼在哪裏呢? [root@localhost ~]# pwd /root [root@localhost ~]# cat .gitconfig [user] name = zhangfengzhe email = zhangfengzhe1990@163.com [color] ui = true 配置文件就在YOUR HOME目錄下,在上面,咱們看到了典型的LINUX分段式配置文件。 所以,咱們能夠直接修改.gitconfig就能夠完成配置。 |
建立Git Repo
Repo即repository的簡寫,就是倉庫,代碼庫的意思,有點MAVEN的感受,呵呵。 先看下面的例子: [root@localhost myproject]# pwd /myproject [root@localhost myproject]# ll total 16 drwxr-xr-x 2 root root 4096 Dec 4 19:41 hadoop drwxr-xr-x 2 root root 4096 Dec 4 19:41 storm [root@localhost myproject]# cd hadoop [root@localhost hadoop]# git init Initialized empty Git repository in /myproject/hadoop/.git/ [root@localhost hadoop]# ll -al total 24 drwxr-xr-x 3 root root 4096 Dec 4 19:41 . drwxr-xr-x 4 root root 4096 Dec 4 19:41 .. drwxr-xr-x 7 root root 4096 Dec 4 19:41 .git [root@localhost hadoop]# 咱們常用的SVN,會在本地目錄下生成.svn,GIT也相似。 經過git init命令,咱們能夠建立一個empty repository! 事實上,對於通常的開發人員而言,咱們並不須要create empty repo,咱們開始須要作的實際上是克隆一個repo。 好比,最近阿里巴巴提交給apache的JSTORM項目,咱們來看看如何CLONE它。 首先,咱們經過https://github.com/alibaba/jstorm COPY HTTPS [root@localhost myproject]# git clone https://github.com/alibaba/jstorm.git 下載完成後,會出現jstorm目錄,以及在目錄中存在.git隱藏目錄。 經過git clone命令,咱們能夠克隆一個repo到本地。 |
添加以及提交
[root@localhost hadoop]# pwd /myproject/hadoop [root@localhost hadoop]# ll -A total 12 drwxr-xr-x 7 root root 4096 Dec 5 03:35 .git -rw-r--r-- 1 root root 0 Dec 5 03:36 HelloWorld.java [root@localhost hadoop]# git status On branch master Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) HelloWorld.java nothing added to commit but untracked files present (use "git add" to track) 首先注意到.git目錄,說明已經進行了init。 經過git status命令,咱們能夠查看repo的狀態信息。 注意到Untracked files列表,是在說明HelloWorld.java沒有註冊到Git,所以咱們須要給HelloWorld.java「上戶口」。 [root@localhost hadoop]# git add HelloWorld.java You have new mail in /var/spool/mail/root [root@localhost hadoop]# git status On branch master Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: HelloWorld.java [root@localhost hadoop]# 經過git add命令,其實是將file推送到Staged Area。 上面再次查看狀態,提示須要提交,HelloWorld.java is new file。 下面咱們來提交: [root@localhost hadoop]# git commit -m "this is the first commit for me and only one file : HelloWorld.java" [master (root-commit) 815b551] this is the first commit for me and only one file : HelloWorld.java 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 HelloWorld.java [root@localhost hadoop]# 注意了,同SVN同樣,GIT每次提交也會有MESSAGE信息,直接經過-m選項進行指定。 經過git commit -m命令來進行提交到HISTORY區域。 那麼提交後的狀態,又是什麼呢? [root@localhost hadoop]# git status On branch master nothing to commit, working directory clean [root@localhost hadoop]# 提交後,就乾淨了,你懂的! 那麼經過上面的一些實踐,其實咱們能夠獲得一些初步的認識: 若是有FILE並無ADD到REPO的話,GIT會提示咱們Untracked files 若是git add FILE但沒有COMMIT的話,GIT會提示咱們new files 若是COMMIT後,GIT會提示咱們nothing to commit, working directory clean |
初步認識Git的核心原理圖
在上面的例子中,已經說起到working directory,staged area以及history。 其實這三個區域就是GIT的核心,理解他們之間的關係,是掌握GIT的基礎。 咱們工做在working dir區域,對文件進行改動、添加、刪除的操做,而這些改動首先應該先到達Staged area區域,而後經過提交在History區域造成最新version。 既然有3個區域,那麼天然,對於一個文件,應該有2部分的狀態信息: 第一,對於working dir和staged area而言,有什麼區別? 第二,對於staged area和history而言,有什麼區別? 事實上,對於git status -s會看到2列狀態標誌位來表達這2部分狀態信息。【後文會有介紹】 對於History有一個HEAD的概念: 提及head,天然會想到頭部指針,確實是有這麼個意思。 關於HEAD,也會在命令中予以體現! |
Git狀態標誌位剖析
[root@localhost hadoop]# git status On branch master nothing to commit, working directory clean [root@localhost hadoop]# ll -a total 28 drwxr-xr-x 3 root root 4096 Dec 5 03:36 . drwxr-xr-x 4 root root 4096 Dec 4 20:08 .. drwxr-xr-x 8 root root 4096 Dec 5 04:01 .git -rw-r--r-- 1 root root 0 Dec 5 03:36 HelloWorld.java [root@localhost hadoop]# vi HelloWorld.java [root@localhost hadoop]# git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: HelloWorld.java no changes added to commit (use "git add" and/or "git commit -a") [root@localhost hadoop]# [root@localhost hadoop]# git status -s M HelloWorld.java ?? love.txt [root@localhost hadoop]# git add love.txt [root@localhost hadoop]# git status -s M HelloWorld.java A love.txt 注意git status -s會簡明扼要的列出狀態信息,就列出2個標誌位! 仔細觀察上面的信息,love.txt的A,和HelloWorld.java的M並無對齊,這是爲何呢? 實際上,一個文件的git status有2列,第一列表明staging區域信息;第二列表明woring dir信息。也便是說,HelloWorld.java在working dir中修改了,但沒有提交到staging area 。love.txt在staging中添加了,可是在work dir中,沒有改變。 繼續,看下面的操做,來看status的變化: [root@localhost hadoop]# git commit -m "love.txt" love.txt [master f43f700] love.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 love.txt [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# git add HelloWorld.java [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# |
如何查看文件差異?
其實當咱們利用git status發現文件有差別時,很顯然,咱們須要查看文件的差異在哪裏! 看差別,看什麼和什麼的差別呢? 是working dirPK staged area ? 是staged area PK history ? 仍是working dir PK history ? git均可以知足你! working dir PK staged area: [root@localhost hadoop]# git status -s MM HelloWorld.java [root@localhost hadoop]# git diff diff --git a/HelloWorld.java b/HelloWorld.java index 2e3abaa..5e6618e 100644 --- a/HelloWorld.java +++ b/HelloWorld.java @@ -1 +1,2 @@ this is not a java file,haha +abc [root@localhost hadoop]# staged area PK history: [root@localhost hadoop]# git diff --staged working dir PK history: [root@localhost hadoop]# git status -s MM HelloWorld.java [root@localhost hadoop]# git diff HEAD diff --git a/HelloWorld.java b/HelloWorld.java index e69de29..5e6618e 100644 --- a/HelloWorld.java +++ b/HelloWorld.java @@ -0,0 +1,2 @@ +this is not a java file,haha +abc [root@localhost hadoop]# git diff/git diff --staged/git diff HEAD 查看文件差別。 git diff列出的信息也是蠻多的,固然能夠像git status -s那樣有簡化版本: git diff --stat [root@localhost hadoop]# git diff --stat HEAD HelloWorld.java | 2 ++ 1 file changed, 2 insertions(+) [root@localhost hadoop]# |
Git有後悔藥能夠吃!
有一句老話叫 人非聖賢,孰能無過。 那麼在GIT中,如何撤銷錯誤呢? 既然是撤銷錯誤,那麼是從哪裏撤銷到哪裏呢? 在實際開發中,咱們常常遇到的是這樣的狀況,咱們對working dir的FILE進行了修改,而後ADD到了staged area區域,忽然發現有問題,想撤銷這些改動。 SO EASY,咱們只須要將history的內容還原便可。 [root@localhost hadoop]# ll -A total 20 drwxr-xr-x 8 root root 4096 Dec 5 06:20 .git -rw-r--r-- 1 root root 33 Dec 5 04:56 HelloWorld.java -rw-r--r-- 1 root root 0 Dec 5 04:06 love.txt [root@localhost hadoop]# vi HelloWorld.java [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# git add HelloWorld.java [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# git reset HelloWorld.java Unstaged changes after reset: M HelloWorld.java [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# 能夠發現經過git reset命令將staging area還原至history版本,須要注意是的不影響WORK DIR的改動。其實,就是一個標誌位的還原操做而已。 那若是咱們想把已經修改的WORK DIR的文件也恢復到原來的狀態,怎麼辦呢? 同上,咱們只須要將STAGING AREA的文件覆蓋WORK DIR便可,利用git checkout命令。 [root@localhost hadoop]# more HelloWorld.java this is not a java file,haha abc woyaogaini [root@localhost hadoop]# git checkout HelloWorld.java [root@localhost hadoop]# git status -s [root@localhost hadoop]# more HelloWorld.java this is not a java file,haha abc [root@localhost hadoop]# 注意,git提供了一個簡化命令git checkout HEAD,它等價於下面的操做: git checkout HEAD = git reset + git checkout [root@localhost hadoop]# git status -s [root@localhost hadoop]# ll -A total 24 drwxr-xr-x 8 root root 4096 Dec 5 06:34 .git -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 11 Dec 5 06:34 love.txt [root@localhost hadoop]# cat love.txt i love you [root@localhost hadoop]# vi love.txt [root@localhost hadoop]# cat love.txt i love you do you love me [root@localhost hadoop]# git status -s M love.txt [root@localhost hadoop]# git add love.txt [root@localhost hadoop]# git status -s M love.txt [root@localhost hadoop]# git checkout HEAD love.txt [root@localhost hadoop]# git status -s [root@localhost hadoop]# cat love.txt i love you [root@localhost hadoop]# |
移除及重命名文件
[root@localhost hadoop]# ll total 16 -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# git status -s [root@localhost hadoop]# touch delete.log [root@localhost hadoop]# git add delete.log [root@localhost hadoop]# git commit -m "commit" [master 0eccf50] commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 delete.log [root@localhost hadoop]# git status On branch master nothing to commit, working directory clean [root@localhost hadoop]# git rm delete.log rm 'delete.log' [root@localhost hadoop]# git status -s D delete.log [root@localhost hadoop]# ll -A total 24 drwxr-xr-x 8 root root 4096 Dec 5 06:53 .git -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# 看得出,利用git rm進行刪除後,須要COMMIT! [root@localhost hadoop]# git status -s D delete.log [root@localhost hadoop]# git commit -m "commit" [master 415380f] commit 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 delete.log [root@localhost hadoop]# git status -s [root@localhost hadoop]# 默認狀況下,git rm會把working dir以及staged area的文件進行刪除。 若是咱們僅僅想從STAGING AREA中移除FILE,可是保留WORK DIR中的文件的話,能夠這樣操做: [root@localhost myproject]# ll total 16 drwxr-xr-x 3 root root 4096 Dec 5 06:53 hadoop drwxr-xr-x 2 root root 4096 Dec 4 19:41 storm [root@localhost myproject]# cd hadoop/ [root@localhost hadoop]# ll total 16 -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# git status -s [root@localhost hadoop]# touch delete.log [root@localhost hadoop]# git status -s ?? delete.log [root@localhost hadoop]# git add delete.log [root@localhost hadoop]# git commit -m "commit" [master 48b1bad] commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 delete.log [root@localhost hadoop]# git status -s [root@localhost hadoop]# ll total 20 -rw-r--r-- 1 root root 0 Dec 5 17:26 delete.log -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# git rm -cached delete.log error: did you mean `--cached` (with two dashes ?) [root@localhost hadoop]# git rm --cached delete.log rm 'delete.log' [root@localhost hadoop]# ll total 20 -rw-r--r-- 1 root root 0 Dec 5 17:26 delete.log -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# git status -s D delete.log ?? delete.log [root@localhost hadoop]# git rm --cached的方式: 從最後的狀態能夠看到,delete.log仍然在WORK DIR中,可是並無ADD到STAGING AREA區域,同時STAGING AREA區域的delete.log被刪除。 重命名操做: [root@localhost hadoop]# ll -A total 28 -rw-r--r-- 1 root root 0 Dec 5 17:26 delete.log drwxr-xr-x 8 root root 4096 Dec 5 17:31 .git -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt [root@localhost hadoop]# git status -s [root@localhost hadoop]# git mv delete.log delete.me [root@localhost hadoop]# git status -s R delete.log -> delete.me [root@localhost hadoop]# git commit -m "rename file" [master 6f26a1b] rename file 1 file changed, 0 insertions(+), 0 deletions(-) rename delete.log => delete.me (100%) [root@localhost hadoop]# git status -s [root@localhost hadoop]# 經過git mv便可重命名,須要COMMIT! |
保留現場:暫存工做區
什麼叫暫存工做區呢? 好比在實際開發中,咱們常常遇到這樣的場景: 咱們在WORK DIR中進行修改,有時咱們還add了一部分到staging area,此時忽然發現代碼存在BUG,須要修改。固然,咱們能夠利用git reset+git checkout的方式迅速獲得clean code,而後開始修改,可是這樣咱們就丟失了在work dir中的全部改動。 git爲咱們提供了git stash命令,幫助咱們保存現有的工做區,於此同時work dir /staging area的代碼恢復到HISTORY水平。一旦咱們改動完畢,COMMIT到HISTORY後,利用git stash pop進行還原原來的工做區! [root@localhost hadoop]# git status -s [root@localhost hadoop]# ll total 28 -rw-r--r-- 1 root root 7 Dec 5 18:07 delete.me -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt -rw-r--r-- 1 root root 0 Dec 5 17:40 t1.txt [root@localhost hadoop]# vi delete.me [root@localhost hadoop]# cat delete.me hello , world [root@localhost hadoop]# git status -s M delete.me [root@localhost hadoop]# git add delete.me [root@localhost hadoop]# git status -s M delete.me [root@localhost hadoop]# vi delete.me [root@localhost hadoop]# git status -s MM delete.me [root@localhost hadoop]# git stash Saved working directory and index state WIP on master: b714e98 commit HEAD is now at b714e98 commit [root@localhost hadoop]# git status -s [root@localhost hadoop]# ll total 28 -rw-r--r-- 1 root root 7 Dec 5 18:11 delete.me -rw-r--r-- 1 root root 33 Dec 5 06:26 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt -rw-r--r-- 1 root root 0 Dec 5 17:40 t1.txt [root@localhost hadoop]# vi HelloWorld.java [root@localhost hadoop]# git status -s M HelloWorld.java [root@localhost hadoop]# git add HelloWorld.java [root@localhost hadoop]# git commit -m "bug fix" [master 54cf628] bug fix 1 file changed, 1 insertion(+) [root@localhost hadoop]# git status -s [root@localhost hadoop]# git stash pop On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: delete.me no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (963a3ab0075e09ee63117b6b8b606780aca5d020) [root@localhost hadoop]# ll total 28 -rw-r--r-- 1 root root 26 Dec 5 18:12 delete.me -rw-r--r-- 1 root root 37 Dec 5 18:11 HelloWorld.java -rw-r--r-- 1 root root 31 Dec 5 06:42 love.txt -rw-r--r-- 1 root root 0 Dec 5 17:40 t1.txt [root@localhost hadoop]# cat delete.me hello , world hello , git [root@localhost hadoop]# git status -s M delete.me [root@localhost hadoop]# |
總結
到這裏就結束了,下篇博客將會繼續介紹GIT的一些深刻知識,好比COMMIT對象、TREE-ISH表達式、建立/刪除/合併分支等。 |