<<git使用快速教程>>
Tags: linux-tool
file:///home/scr/.rt/linux/computor/tools/vercol/git/books/Pro-Git/zh/index.html
1. 基础
1.1 取得项目的 Git 仓库
1.1.1 在工作目录中初始化新仓库
要对现有的某个项目开始用 Git 管理, 只需到此项目所在的目录, 执行:
$ git init
初始化后, 在当前目录下会出现一个名为 .git 的目录, 所有 Git 需要的数据和资源都
存放在这个目录中. 不过目前, 仅仅是按照既有的结构框架初始化好了里边所有的文件和
目录, 但我们还没有开始跟踪管理项目中的任何一个文件. (在第九章我们会详细说明刚
才创建的 .git 目录中究竟有哪些文件, 以及都起些什么作用. )
如果当前目录下有几个文件想要纳入版本控制, 需要先用 git add 命令告诉 Git 开始对
这些文件进行跟踪, 然后提交:
$ git add *.c
$ git add README
$ git commit -m 'initial project version'
稍后我们再逐一解释每条命令的意思. 不过现在, 你已经得到了一个实际维护着若干文件
的 Git 仓库.
1.1.2 从现有仓库克隆
如果想对某个开源项目出一份力, 可以先把该项目的 Git 仓库复制一份出来, 这就需要
用到 git clone 命令. 如果你熟悉其他的 VCS 比如 Subversion, 你可能已经注意到这
里使用的是 clone 而不是 checkout. 这是个非常重要的差别, Git 收取的是项目历史的
所有数据(每一个文件的每一个版本), 服务器上有的数据克隆之后本地也都有了. 实际上
, 即便服务器的磁盘发生故障, 用任何一个克隆出来的客户端都可以重建服务器上的仓库
, 回到当初克隆时的状态(虽然可能会丢失某些服务器端的挂钩设置, 但所有版本的数据
仍旧还在, 有关细节请参考第四章).
克隆仓库的命令格式为 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 传输协议.
我们会在第四章详细介绍所有这些协议在服务器端该如何配置使用, 以及各种方式之间的
利弊.
1.2 记录每次更新到仓库
1.2.1 检查当前文件状态
要确定哪些文件当前处于什么状态, 可以用 git status 命令. 如果在克隆仓库之后立即
执行此命令, 会看到类似这样的输出:
$ git status
# On branch master
nothing to commit (working directory clean)
1.2.2 跟踪新文件
使用命令 git add 开始跟踪一个新文件. 所以, 要跟踪 README 文件, 运行:
$ 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
#
1.2.3 暂存已修改文件
现在我们修改下之前已跟踪过的文件 benchmarks.rb, 然后再次运行 status 命令, 会看
到这样的状态报告:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: benchmarks.rb
#
文件 benchmarks.rb 出现在 "Changed but not updated" 这行下面, 说明已跟踪文件
的内容发生了变化, 但还没有放到暂存区. 要暂存这次更新, 需要运行 git add 命令(
这是个多功能命令, 根据目标文件的状态不同, 此命令的效果也不同: 可以用它开始跟踪
新文件, 或者把已跟踪的文件放到暂存区, 还能用于合并时把有冲突的文件标记为已解决
状态等). 现在让我们运行 git add 将 benchmarks.rb 放到暂存区, 然后再看看 git
status 的输出:
$ 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
#
NOTE:
现在两个文件都已暂存, 下次提交时就会一并记录到仓库. 假设此时, 你想要在
benchmarks.rb 里再加条注释, 重新编辑存盘后, 准备好提交. 不过且慢, 再运行 git
status 看看:
$ vim benchmarks.rb
$ git status
# 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
#
怎么回事?benchmarks.rb 文件出现了两次!一次算未暂存, 一次算已暂存, 这怎么可能
呢?好吧, 实际上 Git 只不过暂存了你运行 git add 命令时的版本, 如果现在提交, 那
么提交的是添加注释前的版本, 而非当前工作目录中的版本. 所以, 运行了 git add 之
后又作了修订的文件, 需要重新运行 git 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
#
1.2.4 忽略某些文件
一般我们总会有些文件无需纳入 Git 的管理, 也不希望它们总出现在未跟踪文件列表.
通常都是些自动生成的文件, 比如日志文件, 或者编译过程中创建的临时文件等. 我们可
以创建一个名为 .gitignore 的文件, 列出要忽略的文件模式. 来看一个实际的例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件. 一般这类对象文件和存档文件都是
编译过程中出现的, 我们用不着跟踪它们的版本. 第二行告诉 Git 忽略所有以波浪符(~)
结尾的文件, 许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本. 此外, 你
可能还需要忽略 log, tmp 或者 pid 目录, 以及自动生成的文档等等. 要养成一开
始就设置好 .gitignore 文件的习惯, 以免将来误提交这类无用的文件.
文件 .gitignore 的格式规范如下:
* 所有空行或者以注释符号 # 开头的行都会被 Git 忽略.
* 可以使用标准的 glob 模式匹配. * 匹配模式最后跟反斜杠(/)说明要忽略的是目
录. * 要忽略指定模式以外的文件或目录, 可以在模式前加上惊叹号(!)取反.
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式. 星号(*)匹配零个或多个任
意字符; [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a, 要么匹配
一个 b, 要么匹配一个 c); 问号(?)只匹配一个任意字符; 如果在方括号中使用短划线分
隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0
到 9 的数字).
我们再看一个 .gitignore 文件的例子:
# 此为注释 - 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件, 不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
1.2.5 查看已暂存和未暂存的更新
// 前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交?
$ git status
// 要查看尚未暂存的文件更新了哪些部分, 不加参数直接输入 git diff:
// 此命令比较的是工作目录中当前文件和暂存区域快照之间的差异, 也就是修改之后还
// 没有暂存起来的变化内容.
$ git diff
// 若要看已经暂存起来的文件和上次提交时的快照之间的差异, 可以用 git diff --cached
$ git diff --cached
1.2.6 提交更新
现在的暂存区域已经准备妥当可以提交了.
// 这种方式会启动文本编辑器以便输入本次提交的说明.
$ git commit
// 可以用 -v 选项将修改差异的每一行都包含到注释中来
$ git commit -v
// 另外也可以用 -m 参数后跟提交说明的方式, 在一行命令中提交更新:
$ git commit -m "Story 182: Fix benchmarks for speed"
1.2.7 跳过使用暂存区域
尽管使用暂存区域的方式可以精心准备要提交的细节, 但有时候这么做略显繁琐. Git 提
供了一个跳过使用暂存区域的方式, 只要在提交的时候, 给 git commit 加上 -a 选项,
Git 就会自动把所有已经跟踪过的文件暂存起来一并提交, 从而跳过 git add 步骤:
$ git status
# On branch master
#
# Changed but not updated:
#
# modified: benchmarks.rb
#
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 files changed, 5 insertions(+), 0 deletions(-)
看到了吗?提交之前不再需要 git add 文件 benchmarks.rb 了.
1.2.8 移除文件
要从 Git 中移除某个文件, 就必须要从已跟踪文件清单中移除(确切地说, 是从暂存区域
移除), 然后提交. 可以用 git rm 命令完成此项工作, 并连带从工作目录中删除指定的
文件, 这样以后就不会出现在未跟踪文件清单中了.
// 如果只是简单地从工作目录中手工删除文件, 运行 git status 时就会在 "Changed
// but not updated" 部分(也就是_未暂存_清单)看到:
$ rm grit.gemspec
$ git status
# On branch master
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
#
# deleted: grit.gemspec
#
// 然后再运行 git rm 记录此次移除文件的操作:
$ git rm grit.gemspec
rm 'grit.gemspec'
$ git status
# On branch master
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: grit.gemspec
#
最后提交的时候, 该文件就不再纳入版本管理了. 如果删除之前修改过并且已经放到暂存
区域的话, 则必须要用强制删除选项 -f(译注: 即 force 的首字母), 以防误删除文件后
丢失修改的内容.
另外一种情况是, 我们想把文件从 Git 仓库中删除(亦即从暂存区域移除), 但仍然希望
保留在当前工作目录中. 换句话说, 仅是从跟踪清单中删除. 比如一些大型日志文件或者
一堆 .a 编译文件, 不小心纳入仓库后, 要移除跟踪但不删除文件, 以便稍后在
.gitignore 文件中补上, 用 --cached 选项即可:
// 把文件从 Git 仓库中删除(亦即从暂存区域移除), 但仍然希望保留在当前工作目录中
$ git rm --cached readme.txt
// 后面可以列出文件或者目录的名字, 也可以使用 glob 模式. 比方说:
$ git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式, 所以我们
不用 shell 来帮忙展开(译注: 实际上不加反斜杠也可以运行, 只不过按照 shell 扩展
的话, 仅仅删除指定目录下的文件而不会递归匹配. 上面的例子本来就指定了目录
Tags: linux-tool
file:///home/scr/.rt/linux/computor/tools/vercol/git/books/Pro-Git/zh/index.html
1. 基础
1.1 取得项目的 Git 仓库
1.1.1 在工作目录中初始化新仓库
要对现有的某个项目开始用 Git 管理, 只需到此项目所在的目录, 执行:
$ git init
初始化后, 在当前目录下会出现一个名为 .git 的目录, 所有 Git 需要的数据和资源都
存放在这个目录中. 不过目前, 仅仅是按照既有的结构框架初始化好了里边所有的文件和
目录, 但我们还没有开始跟踪管理项目中的任何一个文件. (在第九章我们会详细说明刚
才创建的 .git 目录中究竟有哪些文件, 以及都起些什么作用. )
如果当前目录下有几个文件想要纳入版本控制, 需要先用 git add 命令告诉 Git 开始对
这些文件进行跟踪, 然后提交:
$ git add *.c
$ git add README
$ git commit -m 'initial project version'
稍后我们再逐一解释每条命令的意思. 不过现在, 你已经得到了一个实际维护着若干文件
的 Git 仓库.
1.1.2 从现有仓库克隆
如果想对某个开源项目出一份力, 可以先把该项目的 Git 仓库复制一份出来, 这就需要
用到 git clone 命令. 如果你熟悉其他的 VCS 比如 Subversion, 你可能已经注意到这
里使用的是 clone 而不是 checkout. 这是个非常重要的差别, Git 收取的是项目历史的
所有数据(每一个文件的每一个版本), 服务器上有的数据克隆之后本地也都有了. 实际上
, 即便服务器的磁盘发生故障, 用任何一个克隆出来的客户端都可以重建服务器上的仓库
, 回到当初克隆时的状态(虽然可能会丢失某些服务器端的挂钩设置, 但所有版本的数据
仍旧还在, 有关细节请参考第四章).
克隆仓库的命令格式为 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 传输协议.
我们会在第四章详细介绍所有这些协议在服务器端该如何配置使用, 以及各种方式之间的
利弊.
1.2 记录每次更新到仓库
1.2.1 检查当前文件状态
要确定哪些文件当前处于什么状态, 可以用 git status 命令. 如果在克隆仓库之后立即
执行此命令, 会看到类似这样的输出:
$ git status
# On branch master
nothing to commit (working directory clean)
1.2.2 跟踪新文件
使用命令 git add 开始跟踪一个新文件. 所以, 要跟踪 README 文件, 运行:
$ 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
#
1.2.3 暂存已修改文件
现在我们修改下之前已跟踪过的文件 benchmarks.rb, 然后再次运行 status 命令, 会看
到这样的状态报告:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: benchmarks.rb
#
文件 benchmarks.rb 出现在 "Changed but not updated" 这行下面, 说明已跟踪文件
的内容发生了变化, 但还没有放到暂存区. 要暂存这次更新, 需要运行 git add 命令(
这是个多功能命令, 根据目标文件的状态不同, 此命令的效果也不同: 可以用它开始跟踪
新文件, 或者把已跟踪的文件放到暂存区, 还能用于合并时把有冲突的文件标记为已解决
状态等). 现在让我们运行 git add 将 benchmarks.rb 放到暂存区, 然后再看看 git
status 的输出:
$ 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
#
NOTE:
现在两个文件都已暂存, 下次提交时就会一并记录到仓库. 假设此时, 你想要在
benchmarks.rb 里再加条注释, 重新编辑存盘后, 准备好提交. 不过且慢, 再运行 git
status 看看:
$ vim benchmarks.rb
$ git status
# 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
#
怎么回事?benchmarks.rb 文件出现了两次!一次算未暂存, 一次算已暂存, 这怎么可能
呢?好吧, 实际上 Git 只不过暂存了你运行 git add 命令时的版本, 如果现在提交, 那
么提交的是添加注释前的版本, 而非当前工作目录中的版本. 所以, 运行了 git add 之
后又作了修订的文件, 需要重新运行 git 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
#
1.2.4 忽略某些文件
一般我们总会有些文件无需纳入 Git 的管理, 也不希望它们总出现在未跟踪文件列表.
通常都是些自动生成的文件, 比如日志文件, 或者编译过程中创建的临时文件等. 我们可
以创建一个名为 .gitignore 的文件, 列出要忽略的文件模式. 来看一个实际的例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件. 一般这类对象文件和存档文件都是
编译过程中出现的, 我们用不着跟踪它们的版本. 第二行告诉 Git 忽略所有以波浪符(~)
结尾的文件, 许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本. 此外, 你
可能还需要忽略 log, tmp 或者 pid 目录, 以及自动生成的文档等等. 要养成一开
始就设置好 .gitignore 文件的习惯, 以免将来误提交这类无用的文件.
文件 .gitignore 的格式规范如下:
* 所有空行或者以注释符号 # 开头的行都会被 Git 忽略.
* 可以使用标准的 glob 模式匹配. * 匹配模式最后跟反斜杠(/)说明要忽略的是目
录. * 要忽略指定模式以外的文件或目录, 可以在模式前加上惊叹号(!)取反.
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式. 星号(*)匹配零个或多个任
意字符; [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a, 要么匹配
一个 b, 要么匹配一个 c); 问号(?)只匹配一个任意字符; 如果在方括号中使用短划线分
隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0
到 9 的数字).
我们再看一个 .gitignore 文件的例子:
# 此为注释 - 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件, 不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
1.2.5 查看已暂存和未暂存的更新
// 前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交?
$ git status
// 要查看尚未暂存的文件更新了哪些部分, 不加参数直接输入 git diff:
// 此命令比较的是工作目录中当前文件和暂存区域快照之间的差异, 也就是修改之后还
// 没有暂存起来的变化内容.
$ git diff
// 若要看已经暂存起来的文件和上次提交时的快照之间的差异, 可以用 git diff --cached
$ git diff --cached
1.2.6 提交更新
现在的暂存区域已经准备妥当可以提交了.
// 这种方式会启动文本编辑器以便输入本次提交的说明.
$ git commit
// 可以用 -v 选项将修改差异的每一行都包含到注释中来
$ git commit -v
// 另外也可以用 -m 参数后跟提交说明的方式, 在一行命令中提交更新:
$ git commit -m "Story 182: Fix benchmarks for speed"
1.2.7 跳过使用暂存区域
尽管使用暂存区域的方式可以精心准备要提交的细节, 但有时候这么做略显繁琐. Git 提
供了一个跳过使用暂存区域的方式, 只要在提交的时候, 给 git commit 加上 -a 选项,
Git 就会自动把所有已经跟踪过的文件暂存起来一并提交, 从而跳过 git add 步骤:
$ git status
# On branch master
#
# Changed but not updated:
#
# modified: benchmarks.rb
#
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 files changed, 5 insertions(+), 0 deletions(-)
看到了吗?提交之前不再需要 git add 文件 benchmarks.rb 了.
1.2.8 移除文件
要从 Git 中移除某个文件, 就必须要从已跟踪文件清单中移除(确切地说, 是从暂存区域
移除), 然后提交. 可以用 git rm 命令完成此项工作, 并连带从工作目录中删除指定的
文件, 这样以后就不会出现在未跟踪文件清单中了.
// 如果只是简单地从工作目录中手工删除文件, 运行 git status 时就会在 "Changed
// but not updated" 部分(也就是_未暂存_清单)看到:
$ rm grit.gemspec
$ git status
# On branch master
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
#
# deleted: grit.gemspec
#
// 然后再运行 git rm 记录此次移除文件的操作:
$ git rm grit.gemspec
rm 'grit.gemspec'
$ git status
# On branch master
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: grit.gemspec
#
最后提交的时候, 该文件就不再纳入版本管理了. 如果删除之前修改过并且已经放到暂存
区域的话, 则必须要用强制删除选项 -f(译注: 即 force 的首字母), 以防误删除文件后
丢失修改的内容.
另外一种情况是, 我们想把文件从 Git 仓库中删除(亦即从暂存区域移除), 但仍然希望
保留在当前工作目录中. 换句话说, 仅是从跟踪清单中删除. 比如一些大型日志文件或者
一堆 .a 编译文件, 不小心纳入仓库后, 要移除跟踪但不删除文件, 以便稍后在
.gitignore 文件中补上, 用 --cached 选项即可:
// 把文件从 Git 仓库中删除(亦即从暂存区域移除), 但仍然希望保留在当前工作目录中
$ git rm --cached readme.txt
// 后面可以列出文件或者目录的名字, 也可以使用 glob 模式. 比方说:
$ git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式, 所以我们
不用 shell 来帮忙展开(译注: 实际上不加反斜杠也可以运行, 只不过按照 shell 扩展
的话, 仅仅删除指定目录下的文件而不会递归匹配. 上面的例子本来就指定了目录