您的位置:首页 > 其它

E哥的Git教程(二)基础命令

2015-10-25 20:17 423 查看

Git基础命令

“ok,一切准备就绪我们开始git之旅吧。” E哥说,“我来做演示了。你按照我的步骤在自己的笔记本上重做一遍。“

李靖点点头,开始认真的做记录。

建立第一个仓库

首先在开始菜单里找到“Git”->“Git Bash”,弹出命令行窗口。

$ cd /c/users/liyi
$ mkdir mygit
$ cd mygit


在实际工作中,我们遇到的大部分情况都是从已有的Git 远程仓库克隆出一个新的镜像仓库。 克隆仓库的命令格式为
git clone 

“这里
git@github.com:liyi-demo/egit.git
一定要换成你在github
fork
的那个地址,而不能直接用我的仓库地址,因为你不能往我的仓库提交代码。” E哥强调到。

”好的,那我应该用
git@github.com:lijing/egit.git
!“李靖仿照E哥的指示,在自己的笔记本上敲下:

$  git clone git@github.com:lijing/egit.git


检查当前文件状态

你要确定哪些文件当前处于什么状态,可以用 git status 命令。

$ cd egit
$ git status
# On branch master
nothing to commit, working directory clean


这说明你现在的工作目录相当干净,没有任何修改发生过。

添加新文件

在 C:\Users\liyi\mygit\grit 下新建一个空文件 README。

$ vi README


存盘退出。

小贴士:

vi的保存退出命令: 按ESC键 跳到命令模式,然后
:wq
保存并退出.

之后继续在git命令行窗口执行 git status:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       README
nothing added to commit but untracked files present (use "git add" to track)


git返回的信息,告诉我们README这个文件并没有被git版本库管理起来,处于“untracked”状态。使用命令
git add
将新文件放入暂存区,让git开始跟踪它。

$ git add README
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#


只要在 “Changes to be committed” 这行下面的,就说明是已暂存状态(stage),下一步就是等待被提交。

小贴士:

这里的提示“
#   (use "git reset HEAD <file>..." to unstage)
” 是说用 ”git reset HEAD 可以把文件从暂存区重置,退回到刚才文件的untracked状态“。

这里的HEAD一个指针,我们稍后章节会详细说明。

修改文件

“如果是修改一个已经存在的文件会发生什么呢?”E哥自问自答道:“现在在我们刚才克隆下来的egit目录下,有一个benchmarks.rb文件,我们来试试修改这个文件文件。”

vi benchmarks.rb


在文件尾加上一条注释”
# my first comment”
,然后存盘退出。再次运行git status:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   benchmarks.rb
#


文件 benchmarks.rb 出现在 “Changes not staged for commit” 这行下面,说明在git版本控制下的文件内容发生了变化,但还没有放到暂存区(staging area)。需要运行 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
#


现在两个文件都已放到暂存区了。

“那这时如果我再修改benchmarks.rb 会怎么样呢?” 李靖充满好奇的问道。

“git会告诉你本地有文件被修改, 同时暂存区也有要提交的文件。“ E哥回道到,”我们来试一下。“

vi benchmarks.rb


在文件尾加上第二条注释”
#my second comment”
,然后存盘退出。执行命令:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#       modified:   benchmarks.rb
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   benchmarks.rb
#


这时benchmarks.rb出现了两次, 一次是在暂存区的, 一次是修改但未提交暂存区的。这时需要重新运行 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
#


提交更新

现在的暂存区域已经准备妥当可以提交了,运行提交命令 git commit:

$ git commit -m "my first commit"
[master d973af3] my first commit
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 README


“这里需要注意一下!“E哥停下来说道:“刚开始学习git时,提交一定要使用 –m 参数,后面跟上提交的内容注释。这样能养成良好的代码习惯,也能避免很多因为操作系统和编辑器引起的字符乱码问题。”

“这里和svn的使用方法不同,在工作区修改的内容,要先提交到staged区。” 李靖小声的嘟囔道。

E哥看出了李靖的疑惑,走得白板前,指着白板上的那副git三种状态图说:“是的,你看git 使用工作目录,暂存区还有本地仓库来管理本地的文件版本。不在git治理下的文件,git就把他们标为untracked状态。“

“这里应该还要加上一个untracked状态”, E哥接着在白板上画起来,“对于新文件来说,它们是没有进入git版本控制的跟踪之下的,当我们用git add 添加一个新文件时,其实这个命令做了两件事,一是把新文件放入工作目录,二是提交文件到暂存区staged。而commit做的就是把staged中的内容,提交到git版本库中。”



对比文件修改前后

“接下来我要给你介绍比较文件版本区别的命令diff。 这是一个常用的命令,但是它的输出过于难懂,很多人都不是很理解输出的含义。 为了让你打下一个好基础,我们用一个实际例子来演示一下。“ E哥放下墨水笔,走回自己的电脑旁,输入命令:

vi benchmarks.rb


将第6行的 “require ‘pp’” 修改为 “require ‘see diff’”,然后保存退出。



执行命令:

$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 52d4705..43adc7c 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -3,7 +3,7 @@ require 'benchmark'
require 'rubygems'
require 'ruby-prof'
require 'memcache'
-require 'pp'
+require 'see diff'

#require 'grit'


李靖仔细看了一下这些输出,皱了皱眉,泄气得说: “E哥,这些信息量太大了, 我看不明白它返回的是啥意思。”

E哥笑笑说道:“这个的语法有点像机器语言,git就是靠它来一次一次记录文件变动。git往远程服务器推送代码,也是靠这个文件在远程仓库回放来保持代码一致的。 它读起来确实有些晦涩。 不过别泄气,我们一行一行来分析它的含义, 理解了diff输出的每一行内容,你以后就能轻松读懂文件冲突和搞定代码合并了。”

第一行中的
“--git”
表示结果为git格式的diff。a版本的benchmarks.rb(即变动前,版本位于暂存区)和b版本的benchmarks.rb(即变动后,版本位于工作区)。

diff --git a/benchmarks.rb b/benchmarks.rb


第二行表示两个版本的git哈希值(52d4705是修改前的版本, 43adc7c是修改后的版本),100644是文件的类型和权限(前三位是文件类型,例如:100 代表是普通文件;后三位是文件的权限:例如644是只有文件创造者有读写权限,其他用户只有读权限)。

index 52d4705..43adc7c 100644


小贴士:

git可以用到的文件类型包含:

100 : 普通文件(regular file)

101 :文件链接(symbolic link)

111:git链接(gitlink,vista专属的git链接方式)

关于文件权限的设置参考Linux 的
chmod" target=_blank>[/code]。我们现在把github的项目克隆到本地,可以用下面的命令:

$ git clone git@github.com:liyi-demo/egit.git
Cloning into 'egit'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 8 (delta 0), reused 8 (delta 0), pack-reused 0
Receiving objects: 100% (8/8), 1.90 KiB | 0 bytes/s, done.
Checking connectivity... done.


执行完成后,在
C:\Users\liyi\mygit\grit
下看到如下目录:



“这里
git@github.com:liyi-demo/egit.git
一定要换成你在github
fork
的那个地址,而不能直接用我的仓库地址,因为你不能往我的仓库提交代码。” E哥强调到。

”好的,那我应该用
git@github.com:lijing/egit.git
!“李靖仿照E哥的指示,在自己的笔记本上敲下:

$  git clone git@github.com:lijing/egit.git


检查当前文件状态

你要确定哪些文件当前处于什么状态,可以用 git status 命令。

$ cd egit
$ git status
# On branch master
nothing to commit, working directory clean


这说明你现在的工作目录相当干净,没有任何修改发生过。

添加新文件

在 C:\Users\liyi\mygit\grit 下新建一个空文件 README。

$ vi README


存盘退出。

小贴士:

vi的保存退出命令: 按ESC键 跳到命令模式,然后
:wq
保存并退出.

之后继续在git命令行窗口执行 git status:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       README
nothing added to commit but untracked files present (use "git add" to track)


git返回的信息,告诉我们README这个文件并没有被git版本库管理起来,处于“untracked”状态。使用命令
git add
将新文件放入暂存区,让git开始跟踪它。

$ git add README
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#


只要在 “Changes to be committed” 这行下面的,就说明是已暂存状态(stage),下一步就是等待被提交。

小贴士:

这里的提示“
#   (use "git reset HEAD <file>..." to unstage)
” 是说用 ”git reset HEAD 可以把文件从暂存区重置,退回到刚才文件的untracked状态“。

这里的HEAD一个指针,我们稍后章节会详细说明。

修改文件

“如果是修改一个已经存在的文件会发生什么呢?”E哥自问自答道:“现在在我们刚才克隆下来的egit目录下,有一个benchmarks.rb文件,我们来试试修改这个文件文件。”

vi benchmarks.rb


在文件尾加上一条注释”
# my first comment”
,然后存盘退出。再次运行git status:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   benchmarks.rb
#


文件 benchmarks.rb 出现在 “Changes not staged for commit” 这行下面,说明在git版本控制下的文件内容发生了变化,但还没有放到暂存区(staging area)。需要运行 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
#


现在两个文件都已放到暂存区了。

“那这时如果我再修改benchmarks.rb 会怎么样呢?” 李靖充满好奇的问道。

“git会告诉你本地有文件被修改, 同时暂存区也有要提交的文件。“ E哥回道到,”我们来试一下。“

vi benchmarks.rb


在文件尾加上第二条注释”
#my second comment”
,然后存盘退出。执行命令:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#       modified:   benchmarks.rb
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   benchmarks.rb
#


这时benchmarks.rb出现了两次, 一次是在暂存区的, 一次是修改但未提交暂存区的。这时需要重新运行 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
#


提交更新

现在的暂存区域已经准备妥当可以提交了,运行提交命令 git commit:

$ git commit -m "my first commit"
[master d973af3] my first commit
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 README


“这里需要注意一下!“E哥停下来说道:“刚开始学习git时,提交一定要使用 –m 参数,后面跟上提交的内容注释。这样能养成良好的代码习惯,也能避免很多因为操作系统和编辑器引起的字符乱码问题。”

“这里和svn的使用方法不同,在工作区修改的内容,要先提交到staged区。” 李靖小声的嘟囔道。

E哥看出了李靖的疑惑,走得白板前,指着白板上的那副git三种状态图说:“是的,你看git 使用工作目录,暂存区还有本地仓库来管理本地的文件版本。不在git治理下的文件,git就把他们标为untracked状态。“

“这里应该还要加上一个untracked状态”, E哥接着在白板上画起来,“对于新文件来说,它们是没有进入git版本控制的跟踪之下的,当我们用git add 添加一个新文件时,其实这个命令做了两件事,一是把新文件放入工作目录,二是提交文件到暂存区staged。而commit做的就是把staged中的内容,提交到git版本库中。”



对比文件修改前后

“接下来我要给你介绍比较文件版本区别的命令diff。 这是一个常用的命令,但是它的输出过于难懂,很多人都不是很理解输出的含义。 为了让你打下一个好基础,我们用一个实际例子来演示一下。“ E哥放下墨水笔,走回自己的电脑旁,输入命令:

vi benchmarks.rb


将第6行的 “require ‘pp’” 修改为 “require ‘see diff’”,然后保存退出。



执行命令:

$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 52d4705..43adc7c 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -3,7 +3,7 @@ require 'benchmark'
require 'rubygems'
require 'ruby-prof'
require 'memcache'
-require 'pp'
+require 'see diff'

#require 'grit'


李靖仔细看了一下这些输出,皱了皱眉,泄气得说: “E哥,这些信息量太大了, 我看不明白它返回的是啥意思。”

E哥笑笑说道:“这个的语法有点像机器语言,git就是靠它来一次一次记录文件变动。git往远程服务器推送代码,也是靠这个文件在远程仓库回放来保持代码一致的。 它读起来确实有些晦涩。 不过别泄气,我们一行一行来分析它的含义, 理解了diff输出的每一行内容,你以后就能轻松读懂文件冲突和搞定代码合并了。”

第一行中的
“--git”
表示结果为git格式的diff。a版本的benchmarks.rb(即变动前,版本位于暂存区)和b版本的benchmarks.rb(即变动后,版本位于工作区)。

diff --git a/benchmarks.rb b/benchmarks.rb


第二行表示两个版本的git哈希值(52d4705是修改前的版本, 43adc7c是修改后的版本),100644是文件的类型和权限(前三位是文件类型,例如:100 代表是普通文件;后三位是文件的权限:例如644是只有文件创造者有读写权限,其他用户只有读权限)。

index 52d4705..43adc7c 100644


小贴士:

git可以用到的文件类型包含:

100 : 普通文件(regular file)

101 :文件链接(symbolic link)

111:git链接(gitlink,vista专属的git链接方式)

关于文件权限的设置参考Linux 的 [url=http://www.computerhope.com/unix/uchmod.htm]chmod
命令。

第三行表示进行比较的两个文件。

--- a/benchmarks.rb
+++ b/benchmarks.rb


"---"
表示变动前的版本,
"+++"
表示变动后的版本

接下来的就是文件不同处的详细描述

@@ -3,7 +3,7 @@ require 'benchmark'


第一行是用 “
@@ -<start line of hunk>,<number of lines> +<start line of hunk>,<number of lines> @@ [header]”
这样的模式来表示。

Git 使用的是 “Unified diff ” 来比较文件。它把两个比较文件中变化的内容定义为一个hunk(块) ,为了方便阅读, 每个hunk除了修改变化的内容,还包含前后3行没有改动的内容。(见下图)

[header] 主要用来方定位修改出现在文件的那个位置,是diff阅读文件内容,根据正则表达式来判断离hunk最近的header line,例如如果是一个代码文件,diff能定位到变化的代码所处的方法名。 在这里“require ‘benchmark’” 被diff判断为离hunk最近的header。



@@ -3,7 +3,7 @@
表示这次变化的hunk内容, 从变动前的文件第三行开始,总共有7行; 从变动后文件第三行开始,总共7行; 离hunk最近的Header是
“require 'benchmark'”


后面的行表示hunk变动的内容

-require 'pp'
+require 'see diff'


减号(-),表示该行被删除; 加号(+),表示该行为新增

我们现在把修改后的内容,再次提交。

$ git add benchmarks.rb
$ git commit -m "modify benchmarks.rb"


“在多人合作时,经常遇到文件冲突,学会用diff看懂那些地方出现不一致能很方便的定位问题,所以你一定要掌握。” E哥说完把鼻梁上的眼镜往上推了推, 做在椅子上悠闲的往后靠,端起桌上的红茶的喝了一口。

“看来E哥对我的要求很高啊. diff基本的文本格式我了解了,下来我多实践操作一下,争取尽快到达E哥要求的水平!”

[url=/article/10742651.html]上一章《Git热身》

下一章《远程命令》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: