git学习 #2:git基本操作

来源:互联网 发布:怎么在淘宝卖虚拟产品 编辑:程序博客网 时间:2024/04/28 23:54



本文出自   http://blog.csdn.net/shuangde800

---------------------------------------------------------------------------------


本文内容:
初始化一个新的代码仓库,做一些适当配置;
开始或停止跟踪某些文件;
暂存或提交某些更新。
让 Git 忽略某些文件,或是名称符合特定模式的文件;
既快且容易地撤消犯下的小错误;
浏览项目的更新历史,查看某两次更新之间的差异;
如何从远程仓库拉数据下来或者推数据上去。

---------------------------------------------------------------------------------



在工作目录中初始化新仓库

要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:

$ git init
 

如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交

$ git add *.c$ git add README$ git commit -m 'initial project version'
 

从现有仓库克隆

格式: git clone [url]。比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:

$ git clone git://github.com/schacon/grit.git

这会在当前目录下创建一个名为grit的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录,然后从中取出最新版本的文件拷贝。如果进入这个新建的 grit 目录,你会看到项目中的所有文件已经在里边了,准备好后续的开发和使用。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:

$ git clone git://github.com/schacon/grit.git mygrit

唯一的差别就是,现在新建的目录成了 mygrit,其他的都和上边的一样。

Git 支持许多数据传输协议。之前的例子使用的是 git:// 协议,不过你也可以用 http(s):// 或者user@server:/path.git 表示的 SSH 传输协议。我们会在第四章详细介绍所有这些协议在服务器端该如何配置使用,以及各种方式之间的利弊。

 


 

记录每次更新到仓库

工作目录文件的两种状态:已跟踪未跟踪

已跟踪的文件是指本来就被纳入版本控制管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或者已放入暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。

在编辑过某些文件之后,Git 将这些文件标为已修改。我们逐步把这些修改过的文件放到暂存区域,直到最后一次性提交所有这些暂存起来的文件,如此重复。所以使用 Git 时的文件状态变化周期如图 2-1 所示。

 


 

检查当前文件状态

$ git status



跟踪新文件

使用命令 git add 开始跟踪一个新文件。所以,要跟踪 README 文件,运行:

$ git add README

 git add 的潜台词就是把目标文件快照放入暂存区域,也就是 add file into staged area,同时未曾跟踪过的文件标记为需要跟踪。这样就好理解后续 add 操作的实际意义了



忽略某些文件
在.git目录下新建一个名为.gitignore的文件 
.gitignore 的格式规范如下:
  • 所有空行或者以注释符号  开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配。(所谓的 glob 模式是指 shell 所使用的简化了的正则表达式
  • 匹配模式最后跟反斜杠(/)说明要忽略的是目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。

我们再看一个 .gitignore 文件的例子:

# 此为注释 – 将被 Git 忽略# 忽略所有 .a 结尾的文件*.a# 但 lib.a 除外!lib.a# 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO/TODO# 忽略 build/ 目录下的所有文件build/# 会忽略 doc/notes.txt 但不包括 doc/server/arch.txtdoc/*.txt
 


查看已暂存和未暂存的更新

$ git diff

查看尚未暂存的文件更新了哪些部分,此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。

 

$ git diff --cached  
看已经暂存起来的文件和上次提交时的快照之间的差异,
 Git 1.6.1 及更高版本还允许使用 git diff --staged,效果和git diff --cached 命令相同的,但更好记些。



提交更新


每次准备提交前,先用git status 看下,是不是都已暂存起来了,然后再运行提交命令 git commit

$ git commit
这种方式会启动文本编辑器以便输入本次提交的说明。(默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs。当然也可以按照第一章介绍的方式,使用git config --global core.editor 命令设定你喜欢的编辑软件。)


也可以用 -m 参数后跟提交说明的方式,在一行命令中提交更新:
$ git commit -m "Story 182: Fix benchmarks for speed"



跳过使用暂存区域

只要在提交的时候,给 git commit 加上 -a 选项,就可以自动add跟踪的并有改变的文件

 
$ git commit -a -m 'added new benchmarks'
 
 
 

 

移除文件

$ git rm 
从已跟踪文件清单中移除(确切地说,是从暂存区域移除),并连带从工作目录中删除指定的文件,以后就不会出现在未跟踪文件清单中了。

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分.这时要再运行一次git rm filename命令,从已跟踪文件清单中移除。

$ git rm -f 
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母),以防误删除文件后丢失修改的内容。


$ git rm --cached readme.txt
只从跟踪清单中删除,但是仍保留工作目录下的该文件。以后不会跟踪这个文件了。
 

比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上。

 
$ git rm log/\*.log
这是glob模式。此命令会删除log/目录下的所有以.log结尾的文件。星号 * 之前的反斜杠 \,因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开(译注:实际上不加反斜杠也可以运行,只不过按照 shell 扩展的话,仅仅删除指定目录下的文件而不会递归匹配。上面的例子本来就指定了目录,所以效果等同,但下面的例子就会用递归方式匹配,所以必须加反斜杠。)
 
$ git rm \*~

会递归删除当前目录及其子目录中所有 ~ 结尾的文件

 


移动(重命名)文件

$ git mv oldname newname
把oldname文件改名为newname

 



查看提交历史

$ git log   
默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面。

git log 有许多选项可以帮助你搜寻感兴趣的提交,接下来我们介绍些最常用的。

$ git log   -p
我们常用 -p 选项展开显示每次提交的内容差异

$   git  log  -2
用 -2 则仅显示最近的两次更新.-n显示n条

$   git log  --stat
--stat,仅显示简要的增改行数统计

还有个常用的 --pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史。
比如用 --oneline 将每个提交放在一行显示,这在提交数很大时非常有用。另外还有 shortfull 和 fuller 可以用,展示的信息或多或少有些不同
$ git log --pretty = oneline
$ git log --pretty = full
$ git log --pretty = fuller
 

但最有意思的是 format,可以定制要显示的记录格式,这样的输出便于后期编程提取分析,像这样:

$ git log --pretty=format:"%h - %an, %ar : %s"ca82a6d - Scott Chacon, 11 months ago : changed the version number085bb3b - Scott Chacon, 11 months ago : removed unnecessary test codea11bef0 - Scott Chacon, 11 months ago : first commit
 

表 2-1 列出了常用的格式占位符写法及其代表的意义。

选项   说明%H  提交对象(commit)的完整哈希字串%h  提交对象的简短哈希字串%T  树对象(tree)的完整哈希字串%t  树对象的简短哈希字串%P  父对象(parent)的完整哈希字串%p  父对象的简短哈希字串%an 作者(author)的名字%ae 作者的电子邮件地址%ad 作者修订日期(可以用 -date= 选项定制格式)%ar 作者修订日期,按多久以前的方式显示%cn 提交者(committer)的名字%ce 提交者的电子邮件地址%cd 提交日期%cr 提交日期,按多久以前的方式显示%s  提交说明
 

你一定奇怪_作者(author)_和_提交者(committer)_之间究竟有何差别,其实作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人。所以,当你为某个项目发布补丁,然后某个核心成员将你的补丁并入项目时,你就是作者,而那个核心成员就是提交者。


用 oneline 或 format 时结合 --graph 选项,可以看到开头多出一些 ASCII 字符串表示的简单图形,形象地展示了每个提交所在的分支及其分化衍合情况。
$ git log --pretty=format:"%h %s" --graph



以上只是简单介绍了一些 git log 命令支持的选项。表 2-2 还列出了一些其他常用的选项及其释义。

选项  说明-p  按补丁格式显示每个更新之间的差异。--stat  显示每次更新的文件修改统计信息。--shortstat 只显示 --stat 中最后的行数修改添加移除统计。--name-only 仅在提交信息后显示已修改的文件清单。--name-status   显示新增、修改、删除的文件清单。--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。--graph 显示 ASCII 图形表示的分支合并历史。--pretty    使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
 



使用图形化工具查阅提交历史


安装git log的可视化版本工具gitk
$ sudo apt-get install gitk
然后在项目目录下直接输入命令gitk就可直接使用
$ gitk



撤消操作

修改最后一次提交

有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用 --amend 选项重新提交:
$ git commit --amend

此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。

如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交:

$ git commit -m 'initial commit'$ git add forgotten_file$ git commit --amend

上面的三条命令最终只是产生一个提交,第二个提交命令修正了第一个的提交内容。


取消已经暂存的文件

git status 有提示:
 (use "git reset HEAD <file>..." to unstage)
$ git reset HEAD benchmarks.rb
 

取消对文件的修改

git status 提示:
#   (use "git checkout -- <file>..." to discard changes in working directory)
$ git checkout -- benchmarks.rb
 
记住,任何已经提交到 Git 的都可以被恢复。即便在已经删除的分支中的提交,或者用 --amend 重新改写的提交,都可以被恢复(关于数据恢复的内容见第九章)。所以,你可能失去的数据,仅限于没有提交过的,对 Git 来说它们就像从未存在过一样。



远程仓库的使用

查看当前的远程库

$ git remote   
它会列出每个远程库的简短名字,查看当前配置有哪些远程仓库,
在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,
Git 默认使用这个名字来标识你所克隆的原始仓库 
 
$ git remote -v  
显示出克隆项目的地址.如果有多个远程仓库,此命令将全部列出

请注意,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送数据上去(我们会在第四章解释原因)。

添加远程仓库


要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行
$ git remote add [shortname] [url]
例如:
$ git remote add pb git://github.com/paulboone/ticgit.git

 

从远程仓库抓取数据

正如之前所看到的,可以用下面的命令从远程仓库抓取数据到本地:

$ git fetch [remote-name]
此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。
运行完成后,你就可以在本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分支,一探究竟。
记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。

$  git pull
自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。
一般我们运行 git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支

推送数据到远程仓库 

git push [remote-name] [branch-name]

如果要把本地的 master 分支推送到origin 服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行下面的命令:

$ git push origin master
 只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务
 

查看远程仓库信息

我们可以通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息

远程仓库的删除和重命名

重命名
$ git remote rename pb paul

删除
$ git remote rm

打标签

同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签。人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。

列显已有的标签

$ git tag
 
查看某个版本的标签:
$ git tag -l 'v1.4.2.*'
 

新建标签

Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)
轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。
而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。


 

含附注的标签

-a (译注:取 annotated 的首字母)指定标签名字
$ git tag -a v1.4 -m 'my version 1.4'
 

查看相应标签的版本信息,并连同显示打标签时的提交对象:
$ git show v1.4
 

签署标签

如果你有自己的私钥,还可以用 GPG 来签署标签,只需要把之前的 -a 改为 -s (译注: 取signed 的首字母)即可:

$ git tag -s v1.5 -m 'my signed 1.5 tag'
 


轻量级标签

轻量级标签实际上就是一个保存着对应提交对象的校验和信息的文件。要创建这样的标签,一个 -a-s或 -m 选项都不用,直接给出标签名字即可:
$ git tag v1.4-lw



验证标签

可以使用 git tag -v [tag-name] (译注:取 verify 的首字母)的方式验证已经签署的标签。此命令会调用 GPG 来验证签名,所以你需要有签署者的公钥,存放在 keyring 中,才能验证:
$ git tag -v v1.4.2.1


后期加注标签

列出提交历史:
$ git log --pretty=oneline


我们忘了在提交 “updated rakefile” 后为此项目打上版本号 v1.2,没关系,现在也能做。只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可:
$ git tag -a v1.2 9fceb02


分享标签

默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行 git push origin [tagname] 即可:
$ git push origin v1.5

如果要一次推送所有本地新增的标签上去,可以使用 --tags 选项:

$ git push origin --tags