git:开源,分布式版本控制工具。
git基础
设置name和email
git config --global user.name name git config --global user.email email
在工作目录中初始化新仓库
要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:
git init
如果当前目录下有几个文件想要纳入版本控制,需要先用 git add
命令告诉 Git 开始对这些文件进行跟踪,然后提交:
$ git add *.c $ git add README $ git commit -m 'initial project version'
clone
git clone git://github.com/schacon/grit.git
这会在当前目录下创建一个名为 “grit” 的目录,其中内含一个 .git 的目录,并从同步后的仓库中拉出 所有的数据,取出最新版本的文件拷贝。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的 命令最后指定:
git clone git://github.com/schacon/grit.git mygrit
Git 支持许多数据传输协议。之前的例子使用的是 git:// 协议,不过你也可以用 http(s):// 或者 user@server:/ path.git 表示的 SSH 传输协议。
查看当前文件状态
git status
忽略某些文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,像是日志或者编译过程中创建的等等。我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式,来看一个简单的例子:
$ cat .gitignore *.[oa] *~
要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件 .gitignore 的格式规范如下:
• 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。 • 可以使用标准的 glob 模式匹配。 • 匹配模式最后跟反斜杠(/)说明要忽略的是目录。 • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc] 匹配 任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?) 只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配 (比如 [0-9] 表示匹配所有 0 到 9 的数字)。 我们再看一个 .gitignore 文件的例子:
*.a # 忽略所有 .a 结尾的文件 !lib.a # 但 lib.a 除外 /TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO build/ # 忽略 build/ 目录下的所有文件 doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
查看已暂存和未暂存的更新
要查看尚未暂存的文件更新了哪些部分,不加参数直接输入:
git diff
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached 命令。(Git 1.6.1 及更高版本还允许使用 git diff --staged,效果是相同的,但更好记些。)来看看实际的效果:
git diff --staged
提交更新
git commit
可以看到,默认的提交消息包含最后一次运行 git status 的输出,放在注释行里,另外开头还有一空行,供你输入提交说明。
也可以使用 -m 参数后跟提交说明的方式,在一行命令中提交更新
git commit -m "......"
提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版本管理。每一次运行提交操作,都是对项目作一次快照,以后可以回到这个状态,或者进行比较。
跳过暂存区域
给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤。
git commit -a
从git中移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提 交。可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪 文件清单中了。 如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changed but not updated” 部 分(也就是未暂存清单)看到:
git rm ...... rm ......
最后提交的时候,该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f,以防误删除文件后丢失修改的内容。 另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可:
git rm --cached readme.txt git rm log/\*.log #删除log/目录下扩展名为.log的文件
移动文件
git mv file_from file_to git mv相当于: mv README.txt README git rm README.txt git add README
查看提交历史
git log 会按提交时间列出所有的更新,最近的更新排在最上面。每次更新都有一个 SHA-1 校验和、作者的名字和电子邮件地址、提交时间,最后缩进一个段落显示提交说明。
可视化界面:gitk
git log --pretty="%h:%s" --author=gitster --since="2008-10-01" \ --before="2008-11-01" --no-merges -- t/ #查看 Git 仓库中,2008 年 10 月期间,gitster提交的但未合并的测试脚本(位于项目的 t/ 目录下的文件) -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(后跟指定格式)。 -2 则仅显示最近的两次更新 --since=2.weeks 列出最近俩周内的提交 --author 选项显示指定作者的提交 --grep 选项搜索提交说明中的关键字。(请注意,如果要得到同时满足这两个选项搜索条件的提交,就必须用 --all-match 选项。) 如果只关心某些文件或者目录的历史提交,可以在 git log 选项的最后指定它们的路径。因为是放在最后位置上的选项,所以用两个短划线(--)隔开之前的选项和后面限定的路径名。
撤销
修改最后一次提交
撤消刚才的提交操作,使用--amend重新提交
git commit --amend
此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,而所提交的文件快照和之前的一样。 启动文本编辑器后,会看到上次提交时的说明,编辑它确认没问题后保存退出,就会使用新的提交说明覆盖刚才失误的提交。 如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交:
取消已经暂存的文件
git reset HEAD filename
取消对文件的修改
git checkout -- filename
这条命令有些危险,所有对文件的修改都没有了,因为我们刚刚把之前版本的文件复制过来重写了此文件。所以在用这条命令前,请务必确定真的不再需要保留刚才的修改。如果只是想回退版本,同时保留刚才的修改以便将来继续工作,可以用下章介绍的 stashing 和分支来处理,应该会更好些。
远程仓库
查看当前的远程库
git remote -v 显示对应的克隆地址
添加远程仓库
git remote add shortname url #添加之后就可以使用shortname指代对应的仓库地址。 抓取远程仓库有的,但是本地仓库没有的信息: git fetch shortname
从远程仓库抓取数据
git fetch remote-name
此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在本地访问该远程仓库中的所有分支。
推送数据到远程仓库
git push remote-name branch-name 只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次推送。
查看远程仓库信息
git remote show remote-name
远程仓库的删除和重命名
git remote rename oldname newname #改名 git remote rm paul #删除paul仓库
打标签
显示已有的标签
git tag git tag -l 'v1.4.2.*' #只检索1.4.2版本分支
创建含附注的标签
git tag -a v1.4 -m 'my version 1.4'
创建签署标签
如果有自己的私钥,可以用 GPG 来签署标签,只需要把之前的 -a 改为 -s
git tag -s v1.5 -m 'my serison 1.5'
验证标签
git tag -v v1.4.2.1
创建轻量级标签
git tag v1.4-1w #创建一个叫'v1.4-1w'的标签
后期加注标签
git log --pretty=oneline 我们忘了在提交 “updated rakefile” 后为此项目打上版本号 v1.2,没关系,现在也能做。只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可: git tag -a v1.2 9fceb02
分享标签
git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。 git push origin v1.5 如果要一次推送所有(本地新增的)标签上去,可以使用 --tags 选项: git push origin --tags