1、GIT基础教程庞志强2011.12.261、初识 GitGit是一款分布式版本控制系统,有别于 CVS和 SVN等集中式版本控制系统, Git可以让研发团队更加高效的协同工作,从而提高生产率。使用 Git,开发人员的工作不会因为贫乏的遭遇提交冲突而中断,管理人员也无需为数据备份而担心。经过 Linux这样庞大的项目考研之后, Git被证明可以胜任任何规模的团队。2、 Git初始化Git的初始化首先通过下面命令查看 git版本#git version在开始使用 Git之前,我们首先要用 git config命令设置一下 git的配置变量,主要有以下几步:( 1)配置姓名,这个将在提交的时候用到#
2、git config -global user.name “pang”#git config -global user.email ( 2)设置一些别名,以便使用更为简洁的子命令#git config -global alias.ci commit( 3)开启颜色显示#git config -global color.ui true创建版本库及第一次提交首先建立一个新的工作目录,并在这个目录下建立版本库#cd /path/to/my/workspace#mkdir demo#cd demo#git initInitialized empty Git repository in /path/to
3、/demo/.git从上面初始化的输出信息来看,工作区创建了隐藏目录 .git#ls aF./ / .git/这个隐藏的 .git目录就是 Git版本库下面向工作区添加文件#echo “Hello.”welcome.txt将这个文件添加到版本库#git add welcome.txt这里还没有完,需要提交一次才能进入版本库#git commit m “initialized”提交必须有提交说明, -m参数可以直接给出提交说明为什么会有 .git目录在非工作区执行 git命令会因为找不到 .git目录而报错#cd /path/to/my/workspace#git status在工作区建立 a/
4、b/c目录并进入#mkdir p a/b/c#cd a/b/c显示版本库目录#git rev-parse -git-dir显示工作区根目录#git rev-parse -show-toplevel显示工作区间根目录的相对目录#git rev-parse -show-prefix显示当前目录到工作区的深度#git rev-parse -show-cdup git config命令的参数区别执行下面命令,将打开 .git/config文件进行编辑#git config -e执行下面命令,将打开 /home/git/.gitconfig文件进行编辑#git config -e -global执行下面
5、命令,将打开 /etc/gitconfig系统级配置文件进行编辑#git config -e -system以上三个配置文件分别是 Git版本库级别的配置文件、全局配置文件(用户主目录下)和系统级配置文件( /etc目录下)。其优先级别依次降低。谁 在提交?在使用 Git之前我们设置了全局变量 user.name,如果不设置会出现什么后果呢执行下面命令,删除全局变量中的 user.name和 user.email#git config -unset -global user.name#git config -unset -global user.email这样一来,关于用户的设置就被清空了,尝
6、试一下提交#git commit -allow-empty -m “who does commit?”由于没有设置用户,会给出一段警告。查看下提交记录#git log可以看出 Git对于用户姓名进行了大胆猜测,猜测用户为当前终 端登录用户。为了保证提交者信息的准确性,需要对提交恢复用户设置#git config -global user.name “pang”#git config -global user.email #git commit -amend -allow-empty -reset-author其中 -amend参数表示是修补提交,对上一次提交进行修补,而不会产生新的提交。小结
7、了解 了 Git如何初始化版本库及进行提交 熟悉 Git配置变量的设置3、 Git暂存区 修改能直接提交吗?首先更改 welcome.txt文件,在文件后面追加一行。#echo “Nice to meet you.”welcome.txt比较本地与版本库中得差异#git diff可以看到文件修改了,那么提交#git commit -m “Append a nice line.”没有成功,查看提交日志,也没用新的记录#git log#git status -sM welcom.txt添加下修改文件#git add welcome.txt#git diff没有 差别,难道是被提交了 ?在看一下当前
8、状态:#git status -sM welcome.txt两次状态输出有细微的差别,虽然都是 M( modified)标示,但是位置不一样。 git add执行前, M位于第二列,执行后位于第一列。第一 列表示版本库与暂存区的比较,第二列表示工作区与暂存区的区别。通过下面命令进一步体会:#echo “Bye bye.”welcome.txt#git status -sMM welcome.txt#git commit -m “which wersion checked in?”#git status -sM welcome.txt保存下我们的工作,后面的进度恢复会用到。#git stash理
9、解 Git暂存区理解 暂 存区工作区版 库本暂存区 masterobjectsaddcheckoutcommitresetHEADl 图中左侧是工作区,右侧是版本库。版本库包括暂存区,master分支,对象库等。l HEAD实际上是指向分支的一个游标。l 图 中 objects标示的区域是 Git的对象库。l 当对工作区的修改的文件执行 git add命令时,暂存区的目录会被更新,同时工作区的文件会被写入到对象库中。l 当执行提交( git commit)时, master的目录树会根据暂存区做出相应的更新。l 当执行 git reset HEAD命令时,暂存区的目录树会被 master分支的
10、目录树所替换。l 当执行 git checkout .命令时,会用暂存区的文件置换工作区的文件。(危险)l 当执行 git checkout HEAD .命令时,会用 master分支的内容替换暂存区和工作区文件。(危险)目录浏览查看 HEAD目录树#git ls-tree -l HEAD浏览暂存区目录树,先清除工作区改动#git clean -fd#git checkout .对工作区做以下修改#echo “Bye-bye.”welcome.txt#mikdir -p a/b/c#echo “Hello.”a/b/c/hello.txt#git add .#echo “Bye-bye.”a/
11、b/chello.txt#git status -s#find . -path ./.git -prune -o -type -printf “%-20pt%sn”Git Diff 魔法Git Diff工作区版 库本暂存区 masterobjectsGit diff git diff -cachedHEADgit diff HEAD小结 了解 Git的工作原理。 了解 status的用法。 知道工作区,暂存区之间的区别。 学会 diff不同的用法。4、 Git的对象Git里见得最多的就是 40位 16进制的 ID号了 ,产看最近一次提交#git log -1 -pretty=raw通过提交日志
12、,我们发现一个提交里含有 3个 ID:commit:本次提交的唯一标示tree: 本次提交所对应的目录树parent: 本次提交的父提交研究 git对象 ID的一个重要武器就是 git cat-file命令#git cat-file -t ID 查看 ID类型#git cat-file -pID 查看 ID内容通过这个命令就可以对历史提交进行追踪了。对 象库Id e6956Tree f58dParent a0c6commitId a0c6Tree 190dParent 9e8acommitId f58dBlob fd3c|_welcome.txt TreeId fd3cHello.Blob对
13、象 库ID为什么不用顺序数字Git的提交为什么不用顺序数字而采用 40位 16进制,这是因为 Git是一个分布式的版本控制系统。如果采用顺序递增的编号,只能保证本地版本库的唯一性,在分发的时候难免会造成冲突。所以采用 40位 ID可以保证编号的全球唯一。40位的 ID如何访问?对于人来说,要记住 40位的 16进制数是很困难的, Git提供了很多方法可以方便的访问这些 ID。1、不必写全 ID,只采用开头部分(一般 4位以上),只有不与现有其他 ID冲突即可。2、使用 HEAD代表最新提交,则HEAD表示 HEAD的父提交HEAD5表示 HEAD小结 了解 Git对象的概念 通过 ID追踪历史
14、提交5、 Git重置我们知道, master相当于一个分支游标,每次都指向最新的提交。但是既然是游标,就应该既可以向上 “ 游动 ” ,也可以向下 “ 游动 ” 。下面来体会下 master游标是怎么变化的#cat .git/refs/heads/master /查看 master指向#touch new-commit.txt#git add new-commit.txt#git commit -m ”does master change?”#cat .git/refs/heads/master 下面,我们重置下 master游标#git reset -hard HEAD#cat .git/r
15、efs/heads/master 可以看到,不仅刚才提交的文件没了,连提交日志中的记录也不见了。使用重置命令很危险,会彻底丢掉历史。那么,利用浏览提交历史的方法找到丢弃的 ID,在使用重置恢复历史吗?不可能!因为重置让提交历史也改变了。#git log发现提交日志中被丢弃的提交已经不存在了。所以我们无法通过丢弃的 ID来进行恢复。那么,如果不小心进行了错误的重置,应该如何去挽救呢? 利用 reflog挽救错误重置如果没有记下被丢弃的提交 ID,想要重置回原来的提交很麻烦。幸好 Git提供了挽救机制。日志目录下有专门记录分支变更的文件。查看最近 5次变更记录。#tail -5 .git/logs
16、/refs/heads/master#git reflog show master | head -5根据 reflog显示, master2是最后一次提交#git reset master2#git log可以发现提交历史也都恢复了。深入了解 git reset命令 #git reset -q - #git reset -soft|-hard -q 上面两个用法, 是可选项,省略则表示是 HEAD指向的提交。第一种用法包含路径,不会重置引用,也不会改变工作区,相当于取消了之前执行的 git add命令。第二种则会重置引用,根据不同的选项可以对暂存区和工作区进行重置。-hard:替换引用;置换
17、暂存区;置换工作区。-soft: 替换引用。 小结 熟悉 reset重置的用法。 学会利用 reflog恢复错误重置。6、 Git检出重置命令可以更改 master的游标指向,如何能够改变 HEAD的指向呢?HEAD可以理解为头指针,是当前工作区的 “ 基础版本 ” ,当执行提交的时候, HEAD所指向的提交将作为新提交的父提交。下面查看下当前HEAD的指向。#cat .git/HEAD#git branch -v用 git checkout命令检出当前提交的父提交。#git checkout ID查看下现在 HEAD和 master所对应的提交 ID。#git rev-parse HEAD
18、master可以看出当前头指针和 master已经指向了不同的提交。即当前是处于 “ 分离头指针 ” 状态。现在再做一次提交, HEAD会怎么变化呢?#touch detached-commit.txt#git add detached-commit.txt#git commit -m “commit in detached HEAD mode.”#cat .git/HEAD#git log -graph -pretty=oneline可以看到 HEAD指向了最新的提交,并且是建立在之前指向的提交之上的。下面切换到 master分支上。#git checkout master切换之后, HEA
19、D重新指向了分支,而不是断头模式。但是刚才 提交的日志也不见了。#git log -graph -pretty=noeline挽救分离头指针,因为刚才的提交未被任何分支追踪到,因此不能保证这个提交会永远存在于对象库中。#git merge ID 深入理解 git checkout命令 #git checkout -q - #git checkout #git checkout -m -b|-orphan 第一种用法 是可选项,如果省略则相当于从暂存区进行检出。和重置命令不同,重置一般用于重置暂存区,而检出主要是覆盖工作区。这种用法不会改变 HEAD,主要用于指定版本的文件覆盖工作区的对应文件。
20、第二种用法则会改变头指针。只要 HEAD切换到一个分支上才会被跟踪,否则就会处于分离头指针状态。第二种用法主要是用于切换分支的。第三种用法主要是用来创建并切换到新的分支的。新的分支从指定的提交开始。小结 了解检出的作用 初步了解检出的用法7、进度恢复我们在暂存区一节保存了工作进度 Git可以通过下面命令恢复工作进度。#git stash list#git stash pop保存的进度都恢复了,下面进行提交。#git commit -m “add new files:a/b/chello.txt,but leave welcome.txt.”后悔了,重置放弃最新的提交。#git reset -s
21、oft HEAD添加 welcome.txt,撤出 a/b/c/hello.txt#git add welcome.txt#git reset HEAD a/b/c/hello.txt全部清除#git reset#git checkout -welcome.txt#git clean -fdstash的用法:#echo Bye byewelcome.txt#echo hello.hack-1.txt#git add hack-1.txt#git stash save “hacked welcome.txt,newfile hack-1.txt” 工作区恢复了原貌,修改都不见了。#echo fix.hack-2.txt#git stash现在有了两个保存进度,如何恢复第一个进度#git stash apply stash1#git stash clear