前言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表达式、建立/删除/合并分支等。 |