1.取得项目的Git仓库
1. 从当前目录初始化:
git init
初始化后,在当前目录下会出现一个名为.git
的目录
2. 将文件纳入版本控制:
git add *.c
$ git add README
$ git commit -m 'initial project version'
3. 从现有的仓库克隆:
如果想对某个开源项目出一份力,可以先把该项目的 Git 仓库复制一份出来,这就需要用到 git clone
命令。
Git 收取的是项目历史的所有数据(每一个文件的每一个版本),服务器上有的数据克隆之后本地也都有了。实际上,即便服务器的磁盘发生故障,用任何一个克隆出来的客户端都可以重建服务器上的仓库,回到当初克隆时的状态(可能会丢失某些服务器端的挂钩设置,但所有版本的数据仍旧还在,有关细节请参考第四章)。
克隆仓库的命令格式为:git clone [url]
git clone git://github.com/schacon/grit.git
如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令最后指定:
git clone [url] [document]
git clone git://github.com/schacon/grit.git mygrit
4. 提交更新到仓库
工作目录下面的所有文件都不外乎这两种状态:
- 已跟踪:已跟踪的文件是指本来就被纳入版本控制管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或者已放入暂存区。
- 未跟踪:而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。
工作目录中的所有文件都属于已跟踪文件,且状态为未修改。
5. 检查当前文件状态
git status
6. 跟踪新文件
git add README
此时再运行 git status 命令,会看到 README 文件已被跟踪,并处于暂存状态:
git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
git add 后可以接要跟踪的文件或目录的路径。如果是目录的话,就说明要递归跟踪所有该目录下的文件。
7. 暂存已修改的文件
- 首先我们先add一个文件:
git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: README # modified: benchmarks.rb
- 再修改它
-
然后执行git staus查看:
git
On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README modified: benchmarks.rb Changed but not updated: (use "git add <file>..." to update what will be committed) modified: benchmarks.rb
8. 查看已暂存和未暂存的更新
git diff 会使用文件补丁的格式显示具体添加和删除的行
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached 命令。( Git 1.6.1 及更高
版本还允许使用 git diff --staged,效果是相同的,但更好记些。)
请注意,单单 git diff 不过是显示还没有暂存起来的改动,而不是这次工作和上次提交之间的差异。所以有时候你
一下子暂存了所有更新过的文件后,运行 git diff 后却什么也没有,就是这个原因。
9. 提交更新
所以,每次准备提交前,先用 git status 看下,是不是都
已暂存起来了,然后再运行提交命令 git commit:
git commit
记住,提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版本管
理。每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
10. 跳过使用暂存区域
只要在提交的时候,给 git commit 加上 -a 选项, Git 就会自动把所有已经跟踪过的文件暂存起来一并提
交,从而跳过 git add 步骤:
git commit -a -m 'added new benchmarks'
11. 移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “ Changed but not updated” 部分。
git rm
最后提交的时候,该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制
删除选项 -f(译注:即 force 的首字母),以防误删除文件后丢失修改的内容。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可:
git rm --cached readme.txt
后面可以列出文件或者目录的名字,也可以使用 glob 模式。比方说:
git rm log/\*.log
按照 shell 扩展的话,仅仅删除指定目录下的文件而不会递归匹配。
此命令删除所
有 log/ 目录下扩展名为 .log 的文件。类似的比如:
git rm \*~
会递归删除当前目录及其子目录中所有 ~ 结尾的文件。
12.移动文件
不像其他的 VCS 系统, Git 并不跟踪文件移动操作。如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。不过 Git 非常聪明,它会推断出究竟发生了什么,至于具体是如何做到的,我们稍后再谈。
既然如此,当你看到 Git 的 mv 命令时一定会困惑不已。要在 Git 中对文件改名,可以这么做:
git mv file_from file_to
其实,运行 git mv 就相当于运行了下面三条命令:
mv README.txt README
git rm README.txt
git add README
13. 查看提交历史
git log
我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新:
git log –p -2
此外,还有许多摘要选项可以用,比如 --stat,仅显示简要的增改行数统计:
git log --stat
还有个常用的 --pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史。比如用 oneline 将每个提
交放在一行显示,这在提交数很大时非常有用。另外还有 short, full 和 fuller 可以用,展示的信息或多或少有
些不同,请自己动手实践一下看看效果如何。
git log --pretty=oneline
但最有意思的是 format,可以定制要显示的记录格式,这样的输出便于后期编程提取分析,像这样:
git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 11 months ago : changed the verison number
085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code
a11bef0 - Scott Chacon, 11 months ago : first commit
选项 说明
**%H** 提交对象(commit)的完整哈希字串
**%h** 提交对象的简短哈希字串
**%T** 树对象(tree)的完整哈希字串
**%t** 树对象的简短哈希字串
**%P** 父对象(parent)的完整哈希字串
**%p** 父对象的简短哈希字串
**%an** 作者(author)的名字
**%ae** 作者的电子邮件地址
**%ad** 作者修订日期(可以用 -date= 选项定制格式)
**%ar** 作者修订日期,,,按多久以前的方式显示
**%cn** 提交者(committer)*的名字
**%ce** 提交者的电子邮件地址
**%cd** 提交日期
**%cr** 提交日期,按多久以前的方式显示
**%s** 提交说明
你一定奇怪作者(author) 和提交者(committer) 之间究竟有何差别,其实作者指的是实际作出修改的人,提交者指的
是最后将此工作成果提交到仓库的人。所以,当你为某个项目发去补丁,然后某个核心成员将你的补丁并入项目时,
你就是作者,而那个核心成员就是提交者。我们会在第五章再详细介绍两者之间的细致差别。
14. 撤销操作
修改最后一次提交
有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用 --
amend 选项重新提交:
git commit --amend
取消已经暂存的文件
git reset HEAD benchmarks.rb
取消对文件的修改
git checkout -- benchmarks.rb
所以在用这条命令前,请务必确定真的不再需要保留刚才的修改。如果只是想回退版本,同时保留刚才的修改以便将来继续工作,可以用下章介绍的 stashing 和分支来处理,应该会更好些。
15. 远程仓库的使用
远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。同他人协作开发某个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展。
查看当前的远程仓库
要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库, Git 默认使用这个名字来标识你所克隆的原始仓库
git clone git://github.com/schacon/ticgit.git
也可以加上 -v 选项(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址:
git remote -v
origin git://github.com/schacon/ticgit.git
添加远程仓库
git remote add [shortname]
git remote add pb git://github.com/paulboone/ticgit.git
现在可以用字串 pb 指代对应的仓库地址了。比如说,要抓取所有 Paul 有的,但本地仓库没有的信息,可以运行 git fetch pb:
git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
* [new branch] master -> pb/master
* [new branch] ticgit -> pb/ticgit
从远程仓库抓取数据
git fetch [remote-name]
此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分支,一探究竟。
如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以, git fetch origin 会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住, fetch命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
如果设置了某个分支用于跟踪某个远端仓库的分支(参见下节及第三章的内容),可以使用 git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。在日常工作中我们经常这么用,既快且好。
实际上,默认情况下 git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中当前分支。
推送数据到远程仓库
项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name] 。如果要把本地的 master 分支推送到 origin 服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行下面的命令:
git push origin master
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次推送。有关推送数据到远程仓库的详细内容见第三章。
查看远程仓库信息
git remote show [remote-name]
git remote show origin
* remote origin
URL: git://github.com/schacon/ticgit.git
Remote branch merged with 'git pull' while on branch master
master
Tracked remote branches
master
ticgit
远程仓库的删除和重命名
在新版 Git 中可以用 git remote rename 命令修改某个远程仓库的简短名称,比如想把 pb 改成 paul,可以这么
运行:
$ git remote rename pb paul
$ git remote
origin
paul
注意,对远程仓库的重命名,也会使对应的分支名称发生变化,原来的 pb/master 分支现在成了 paul/master。
碰到远端仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不再贡献代码,那么需要移除对应的远端仓库,可以运行 git remote rm 命令:
$ git remote rm paul
$ git remote
origin
16. 打标签
列出现有标签:
git tag
我们可以用特定的搜索模式列出符合条件的标签:
git tag -l 'v1.4.2.*'
新建标签:
- 轻量级的( lightweight):就是个指向特定提交对象的引用
- 含附注的( annotated):存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,
一般我们都建议使用含附注型的标签,以便保留相关信息;
含附注的标签:
创建一个含附注类型的标签非常简单,用 -a (译注:取 annotated 的首字母)指定标签名字即可:
git tag -a v1.4 -m 'my version 1.4'
而 -m 选项则指定了对应的标签说明, Git 会将此说明一同保存在标签对象中。如果在此选项后没有给出具体的说明内容, Git 会启动文本编辑软件供你输入。
可以使用 git show 命令查看相应标签的版本信息,并连同显示打标签时的提交对象。
git show v1.4
签署标签:
只需要把之前的 -a 改为 -s
git tag -s v1.5 -m 'my signed 1.5 tag'
轻量级标签
轻量级标签实际上就是一个保存着对应提交对象的校验和信息的文件。
git tag v1.4-lw
验证标签
git tag -v v1.4.2.1
后期加注标签
git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
我们忘了在提交 “ updated rakefile” 后为此项目打上版本号 v1.2,没关系,现在也能做。只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可:
git tag -a v1.2 9fceb02
分享标签
默认情况下, git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格
式如同推送分支,运行 git push origin [tagname] 即可:
git push orign v1.5
如果要一次推送所有(本地新增的)标签上去,可以使用 --tags 选项:
git push origin --tags
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。