git show HEAD
git show HEAD^
git show HEAD^^
git show HEAD^^^
git diff 486ec madplay/player.c
git diff 4863 856f
git diff 4863:libmad/mad.h 856f:/libmad/mad.h
git-whatchanged utils/audio.sh 列出有哪些版本改动了utils/audio.sh
git-whatchanged -p utils/audio.sh 列出有哪些版本改动了utils/audio.sh并
一一diff
git diff >patch.diff
git -apply -R < ./xxx.diff.patch
git checkout -f丢失本地一切改动,回来树上最新的状态
你可能还想看到每一步改进中的所有完整的 diff ,这可以使用如下命令
$ git log -p
浏览改动的概要对于获得每一步修改的情况常常是比较有用的,可以使用如下
命令
$ git log --stat --summary
git 简要教程
2009-06-02 20:09
原文链接:
http://www.kernel.org/pub/software/scm/git/docs/tutorial.html
这个教程将介绍如何将一个新的项目导入到 git 之中,如何修改项目并如何将
这些变更与其他开发者分享。
如果你更感兴趣如何用 git 取出一个项目,比如,测试软件的最新版本,你可
能更应该看看 The Git User's Manual 的前两章。
首先,记住你可以用 man 来获取 git 的文档,比如 "git diff" 的文档可以用如
下命令察看:
$ man git-diff
在做任何改动之前,最好把自己的名字和 email 地址介绍给大家,最简单的方
法就是:
$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email [email protected]
导入一个新项目
假设你有一个名为 project.tar.gz 的 tarball 作为项目的初始内容。你可以如下
操作来把它至于 git 版本控制之下。
$ tar xzf project.tar.gz
$ cd project
$ git init
Git 将会如下回复:
Initialized empty Git repository in .git/
现在,你已经初始化了工作目录——你可能已经注意到了名为 ".git" 的一个新目
录了。下一步就是使用 git-add(1) 命令告诉 git 当前目录的所有文件全是项目
的一个快照:
$ git add .
这个快照目前存放在一个临时区域之中,在 git 中称为 "index"。使用 git-
commit 命令,你可以把 index 的所有内容永久性地存放到软件仓库之中:
$ git commit
这条命令会向你提示输入版本变更信息。这样,你的项目的第一个版本就已经
存入 git 之中了。
进行修改
修改一些文件之后,你可以将
更新这些内容到 index 之中:
$ git add file1 file2 file3
现在,你已经准备就绪,可以提交了。现在你可以使用 git-diff(1) 命令的 --
cache 参数
来查看都有哪些内容将会被提交:
$ git diff --cached
(如果不使用 --cached 参数,git-diff(1) 会显示所有还没添加进 index 的已经
做出的改动。) 你也可以使用 git-status (1) 来获得一些当前状况的概要信息:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
# modified: file2
# modified: file3
#
如果你需要进行更多改动,现在就可以进行,然后可以添加到 index 之中。最
后,使用如下命令提交改动:
$ git commit
这将再次要求你输入关于这次改动内容的描述性信息,之后记录下
的项目新版本。此外,如果想省掉提交之前的 git add 命令,你可以直接用
$ git commit -a
这样会自动检测所有修改过的文件 (不包括新文件) ,并一气呵成地将它们添到
index 之中,并提交。
关于提交的描述信息: 虽然这个信息不是必须的,但提交信息描述最好以一行不
超过50个字符的概要性信息来开头,在一个空行之后再进行更多的描述。比如
那些将 commit 转化为 email 的工具就会把这个第一行作为邮件标题,其余的
提交内容则放在邮件内部。
Git 跟踪内容而不是文件
很多版本控制系统提供了一个 "add" 命令用来记录一个新文件。而 git 的
"add" 命令更加简单也更加强大: git-add 既用于新文件也用于新近改动的文件
,在所有这些情况下,它在 index 中对所有的文件与状态进行一次快照,这样
就可以在下一次 commit 命令中进行提交。
查看项目历史
在任何时候,你都可以如下查看所有你进行过的改动
$ git log
你可能还想看到每一步改进中的所有完整的 diff ,这可以使用如下命令
$ git log -p
浏览改动的概要对于获得每一步修改的情况常常是比较有用的,可以使用如下
命令
$ git log --stat --summary
管理分支
一个 git 仓库可以包含多个开发分支。使用如下命令可以建立一个称为
"experimental" 的新分支
$ git branch experimental
如果你运行命令
$ git branch
你将可以得到类似下面的已有分支的列表
experimental
* master
"experimental" 就是你刚刚建立的那个分支,而 "master" 分支则是建立仓库
的时候自动创建的缺省分支,里面的星号表示你当前所在的分支;输入命令
$ git checkout experimental
就可以切换到 experimental 分支。现在修改一个文件,并提交改变,然后重
新回到 master 分支:
(edit file)
$ git commit -a
$ git checkout master
你会发现,刚才的变更已经不可见了,这是因为这个改变是发生于
experimental 分支的,而你现在已经回到 master 分支了。
(edit file)
$ git commit -a
这里,两个分支已经产生不同了,每个分支上都发生了不同的改动。要把
experimental 中的改变也合并到 master 之中,运行命令
$ git merge experimental
如果两者的改变并不冲突,那么就算是完成了。而如果这里有冲突,有问题的
文件左边会显示出标记,以表明这个文件发生了冲突;
$ git diff
上述命令将会列出具体的冲突。一旦你编辑文件解决了冲突,
$ git commit -a
这个命令将把合并的结果提交。最终,
$ gitk
会显示出漂亮的图标以展示历史变革。
这里你可以使用如下命令删除 experimental 分支。
$ git branch -d experimental
这个命令会确定 experimental 中的所有改动已经在当前分支当中了。
如果你在 crazy-idea 分支中进行开发,然后又后悔了,你可以用如下命令删除
分支
$ git branch -D crazy-idea
分支操作十分简单而且代价低廉,所以适合于尝试一些东西。
使用 git 进行协作
假设 Alice 在 /home/alice/project 中的 git 仓库启动了一个新项目,而在本
机中也拥有 home 目录的 Bob 想要贡献一些代码。
他可以以如下工作开始:
$ git clone /home/alice/project myrepo
这会新建一个名为 "myrepo" 的目录,里面包含了 Alice 的仓库的一份克隆。
这份克隆与原始项目完全一致,可以处理自己的一份原始项目历史。
之后,Bob 进行了一些变更并提交了这些变动:
(edit files)
$ git commit -a
(repeat as necessary)
当他完成的时候,他告诉 Alice 将 /home/bob/myrepo 之中的变动导入到原
始仓库之中。她使用如下命令来完成这一工作:
$ cd /home/alice/project
$ git pull /home/bob/myrepo master
这 回合并 Bob 的 "master" 分支到 Alice 的当前分支。如果 Alice 也已经修改
了某些内容,她需要手工修复冲突。(注意,"master" 参数实际上并不是必要
的,因为这是缺省分支。) "pull" 命令包括两个操作: 从远端分支中取出改动,
然后合并到当前分支之中。
当你只在一个很小的小组里工作的时候,通常不会频繁地访问同一个仓库。通
过定义仓库的快捷方式,可以让访问远程仓库更方便一些:
$ git remote add bob /home/bob/myrepo
这样,你可以如下用 "git fetch" 命令仅取出改动,而不把它们合并到当前分支
之中:
$ git fetch bob
和长格式不同,当 Alice 使用 git remote 设置的快捷方式从 Bob 的仓库中获
取内容的时候,取出的内容存储在一个 remote tracking 分支之中,在本例中
是 bob/master。所以,如下操作
$ git log -p master..bob/master
将会列出从 Bob 从 Alice 的主分支中分支出去以后的所有改动。
$ git merge bob/master
这个合并也可以通过从自己的 remote tracking 分支中 pull 来做到,如
$ git pull . remotes/bob/master
注意,git pull 总是合并进当前的分支,不论命令行给出的是什么。
之后,Bob 可以如下使用 Alice 的最近改动更新自己的仓库
$ git pull
这里,他不需要给出 Alice 的仓库的位置;当 Bob 克隆了 Alice 的仓库的时候
,git 在仓库设置中保存了她的仓库的位置,即 pull 所使用的位置:
$ git config --get remote.origin.url
/home/bob/myrepo
(git-clone 创建的完整配置信息可以用 "git config -l" 获得,git-config(1) 的
man page 解释了所有选项的含义。)
Git 也在 "origin/master" 分支保存了一份 Alice 的主分支的原始拷贝:
$ git branch -r
origin/master
如果其后 Bob 决定转到另一台主机上工作,他还可以通过 ssh 来克隆原始仓库
:
$ git clone alice.org:/home/alice/project myrepo
此外,git 本身也有远程协议,并且可以使用 rsync 或 http,详细情况可以查
看 git-pull(1) 的 man page。
Git 也可以使用类似 CVS 的工作方式,使用一个中心仓库,所有用户将改动推
送到仓库之中,相关内容可以查阅 git-push(1) 的手册页或 git for CVS users
。
浏览历史
Git 的历史是通过一系列相互关联的 commit 构成的。我们已经通过 git log 命
令看到了这些提交的列表。注意,每个 git log 条目的第一行是那次提交的名称
:
$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <[email protected]>
Date: Tue May 16 17:18:22 2006 -0700
merge-base: Clarify the comments on post processing.
把这个名称用于 git show 命令,可以得到提交的详情。
$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
不过还有其他办法来指代这次提交。你可以只使用名称的开始部分,只要它足
够长,保证在所有提交中是惟一的就行了:
$ git show c82a22c39c # the first few characters of the name are
# usually enough
$ git show HEAD # the tip of the current branch
$ git show experimental # the tip of the "experimental" branch
每一次提交通常都有一次提交作为 "parent" ,它是项目的前一个状态:
$ git show HEAD^ # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD
Note that merge commits may have more than one parent:
要注意,合并提交可能会有多个 "parent":
$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD
你还可以给你的提交一个名字; 命令
$ git-tag v2.5 1b2e1d63ff
让你可以使用 "v2.5" 来指代 1b2e1d63ff。如果你想把这个名字与他人共享 (
比如标记一个发布版本),你应该建立一个 "tag" 对象,可能还需要签署它; 详
情请查看 git-tag(1) 的 man page。
任何 git 命令都可以使用上述任何一种名字。比如:
$ git diff v2.5 HEAD # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
# at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
# directory to its state at HEAD^
小 心使用上述最后一个命令: 这将丢失工作目录中的所有改动,他还会清除本
分支内随后的所有提交。如果这个分支是包含这些提交的惟一分支,它们将永
远地丢失了。此外,不要对一个公众可见的、有其他开发者从中 pull 内容的分
支使用 "git reset" 命令,这将导致一些不必要的合并来清除其他开发者的历史
信息。如果你需要取消已经推送的改动,可以使用 git-revert(1) 命令。
git grep 可以在项目的所有版本历史中寻找字符串,而如下命令
$ git grep "hello" v2.5
会在版本 v2.5 中寻找所有 "hello" 的踪迹。
如果你不提供 commit 名称,git grep 会在你当前的目录中搜索所有由 git 管
理的文件。于是,如下命令
$ git grep "hello"
是搜索 git 跟踪的所有文件的便捷的方式。
很多 git 命令可以处理一组提交,可以通过多种方式来指定版本。这里是一些
git log 的例子:
$ git log v2.5..v2.6 # commits between v2.5 and v2.6
$ git log v2.5.. # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile
你给出的范围的起始值不一定比终止值更老,比如,"stable-release" 分支可
能会在 "master" 分支之后相当长一段时间才会引入同一个提交内容,这样
$ git log stable..experimental
将会列出 expermental 分支之中已经有的,而 stable 分支却还没有的提交,
而命令
$ git log experimental..stable
将会列出 stable 中已有、但 experimental 却没有的提交。
"git log" 命令有一个弱点:必须将所有提交在一个列表中呈现出来。当项目历
史中有多个不同开发分支并最终合并到一起时,"git log" 中呈现出来的顺序可
能没什么意义。
大部分有大量开发者的项目 (比如 linux kernel 或 git 本身) 都经常合并分支,
gitk 可以更好地将这些合并变化展示出来。比如,
$ gitk --since="2 weeks ago" drivers/
这个命令允许你浏览过去两个星期中在 "drivers" 目录之中的任意提交。(注意:
你可以按住 ctrl 键然后用 "-" 和 "+" 来调整 gitk 的字体大小。)
最后,大部分命令可以带有文件名,这可以用于指定某次提交中的某个文件,
从而指定某个文件的某个版本:
$ git diff v2.5:Makefile HEAD:Makefile.in
你还可以用 "git show" 命令去查看任意文件的任意版本:
$ git show v2.5:Makefile
下一步学习
这个教程应该足够你的项目进行基本的项目发布版本管理。不过,要完全深入
地理解 git 的强大功能可能还需要理解两个简单的概念:
* 对象数据库是个相当阳春的系统,用于存储你的项目的历史,包括文件、
目录以及各次提交。
* 索引文件是目录树的状态的缓存,用于建立提交、取出工作目录并保存一
次合并中包含的不同的目录树。
本教程的第二部分 解释了对象数据库、索引文件以及一些其他你在使用 git 中
所需要了解的零七八碎的概念。
如果你不想在这条路上继续下去,还有一些细枝末节的东西可能十分有趣:
*
git-format-patch(1), git-am(1): 用于将一系列 git 提交转化成 email 发
送的补丁或反之,对于 linux 内核这样的高度依赖于邮件发送的补丁的项目来
说十分有用。
* git-bisect(1): 当你的项目发生倒退的时候,一个跟踪发现错误的方法就是
通过历史发现那个罪魁祸首的提交。Git bisect 可以帮助你进行二分查找发现
那个提交。它能在一个有很多分支合并的具有复杂非线性历史的项目中十分灵
巧地进行接近最优的搜索。
*
Everyday GIT with 20 Commands Or So
*
git for CVS users