git init
初始化后,在当前目录下会出现一个名为.git
的目录git
git add *.c $ git add README $ git commit -m 'initial project version'
若是想对某个开源项目出一份力,能够先把该项目的 Git 仓库复制一份出来,这就须要用到 git clone
命令。github
Git 收取的是项目历史的全部数据(每个文件的每个版本),服务器上有的数据克隆以后本地也都有了。实际上,即使服务器的磁盘发生故障,用任何一个克隆出来的客户端均可以重建服务器上的仓库,回到当初克隆时的状态(可能会丢失某些服务器端的挂钩设置,但全部版本的数据仍旧还在,有关细节请参考第四章)。shell
克隆仓库的命令格式为:git clone [url] git clone git://github.com/schacon/grit.git
编程
若是但愿在克隆的时候,本身定义要新建的项目目录名称,能够在上面的命令最后指定:服务器
git clone [url] [document] git clone git://github.com/schacon/grit.git mygrit
网络
工做目录下面的全部文件都不外乎这两种状态:
- 已跟踪:已跟踪的文件是指原本就被归入版本控制管理的文件,在上次快照中有它们的记录,工做一段时间后,它们的状态多是未更新,已修改或者已放入暂存区。
- 未跟踪:而全部其余文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。fetch
工做目录中的全部文件都属于已跟踪文件,且状态为未修改。url
git status
git add README
此时再运行 git status 命令,会看到 README 文件已被跟踪,并处于暂存状态:spa
git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: README #
git add 后能够接要跟踪的文件或目录的路径。若是是目录的话,就说明要递归跟踪全部该目录下的文件。3d
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查看:
gitOn 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
git diff 会使用文件补丁的格式显示具体添加和删除的行
此命令比较的是工做目录中当前文件和暂存区域快照之间的差别,也就是修改以后尚未暂存起来的变化内容。
若要看已经暂存起来的文件和上次提交时的快照之间的差别,能够用 git diff --cached 命令。( Git 1.6.1 及更高
版本还容许使用 git diff --staged,效果是相同的,但更好记些。)
请注意,单单 git diff 不过是显示尚未暂存起来的改动,而不是此次工做和上次提交之间的差别。因此有时候你
一会儿暂存了全部更新过的文件后,运行 git diff 后却什么也没有,就是这个缘由。
因此,每次准备提交前,先用 git status 看下,是否是都
已暂存起来了,而后再运行提交命令 git commit:
git commit
记住,提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,能够在下次提交时归入版本管
理。每一次运行提交操做,都是对你项目做一次快照,之后能够回到这个状态,或者进行比较。
只要在提交的时候,给 git commit 加上 -a 选项, Git 就会自动把全部已经跟踪过的文件暂存起来一并提
交,从而跳过 git add 步骤:
git commit -a -m 'added new benchmarks'
要从 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 \*~
会递归删除当前目录及其子目录中全部 ~ 结尾的文件。
不像其余的 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
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) 之间究竟有何差异,其实做者指的是实际做出修改的人,提交者指的
是最后将此工做成果提交到仓库的人。因此,当你为某个项目发去补丁,而后某个核心成员将你的补丁并入项目时,
你就是做者,而那个核心成员就是提交者。咱们会在第五章再详细介绍二者之间的细致差异。
有时候咱们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操做,可使用 --
amend 选项从新提交:
git commit --amend
git reset HEAD benchmarks.rb
git checkout -- benchmarks.rb
因此在用这条命令前,请务必肯定真的再也不须要保留刚才的修改。若是只是想回退版本,同时保留刚才的修改以便未来继续工做,能够用下章介绍的 stashing 和分支来处理,应该会更好些。
远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些能够写。同他人协做开发某个项目时,须要管理这些远程仓库,以便推送或拉取数据,分享各自的工做进展。
要查看当前配置有哪些远程仓库,能够用 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
git tag
咱们能够用特定的搜索模式列出符合条件的标签:
git tag -l 'v1.4.2.*'
通常咱们都建议使用含附注型的标签,以便保留相关信息;
建立一个含附注类型的标签很是简单,用 -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