博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《pro git》学习手记2
阅读量:6244 次
发布时间:2019-06-22

本文共 10838 字,大约阅读时间需要 36 分钟。

  hot3.png

第二章

获得一个Git库

得到一个Git库有两中主要的方式。一是将一个已经存在的工程或者目录导入到Git里,第二种是从另一个服务器上克隆一个已经存在的Git库。

在一个目录里初始化一个库

$ git init

这会创建一个子目录.git包含了所有必须的库文件(repository files)-一个Git库的框架。此时,你工程里的文件还没有被tracked。如果想track你指定的文件

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

这样你就有了一个拥有tracked文件的Git库了,并且commit一次了。

克隆一个已存在的库

克隆一个库使用git clone [url]。例如克隆Ruby Git 库,它叫Grit,就这样做:

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

这将创建一个目录叫grit,在里面初始化.git目录,从那个库里拉取所有的数据,然后check out一个最新版本的working copy。进入到grit里,你会发现工程文件已经呆在那里了。如果想将库克隆到别的路径叫别的啥名字的话,这样做:

$ git clone git://github.com/schacon/grit.git mygrit
Git有很多传输协议: git://  git协议;http(s):// or user@server:/path.git ssh协议

记录库的改变

工作目录里的每一个文件只能处于tracked或者untracked两种状态中的一种。Tracked文件就是那些最后快照里的文件;它们可能是未修改(unmodified)、已修改(modified)、或者临时的(staged)。Untracked文件是其他的任何文件--也就是在你工作目录里的那些既不再最后的快照里也不在临时区域里的任何文件。当你第一次克隆一个库时,你所有的文件将会是tracked与未修改的(unmodified)因为你刚checkout它们还没有编辑。

当你编辑了文件后,Git就会将它们视为修改的(modified),因为从你想对于你上次提交你已经改变了它们。你临时存储这些已修改的文件(stage these modified files)然后提交所有你临时存储的改变(staged changes),如此反复。这个过程如下图:

18333fig0201-tn.png

文件状态的周期

查看你文件的状态

如果你在克隆之后直接运行这个命令,将会看到这样的效果:

$ git status# On branch masternothing to commit (working directory clean)

这意味着你有一个干净的工作目录-换句话说,没有tracked与modified文件。Git没有发现任何untracked的文件,否则的话它们会被列出来。最后,这个命令告诉你你现在在哪个分支(branch)上。到目前为止,会永远是主分支(master),这是默认的,现在你不用担心这个问题。下一章会详细介绍分支(branch)和引用(reference)。

假设你添加了一个新的文件到你的工程里,一个简单的README文件。如果这个文件以前不存在,运行git status,你将会看到untracked文件像是这样:

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

你会看到新建的README文件是untracked,因为在你的状态输出头上显示的是“Untracked files”。Untracked基本上就意味着Git认为在之前的快照里不存在这个文件。Git不会将它加入到你的提交快照(commit snapshots)里除非你详细告诉它这么做。之所以这样做,是为了防止那些二进制文件或者你不想要包括的文件被无意间添加进commit snapshots里。你确实是想添加进README文件啊,那么就开始tracking它吧。

跟踪(Tracking)新文件

要跟踪一个新文件,使用git add命令。要开始跟踪README文件,可以这样做:

$ git add README
如果你再次运行查看状态命令,将会看到README文件现在是被跟踪的与临时存储的(tracked and staged)。
$ git status# On branch master# Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## new file: README#

你说它是临时存储的是因为它的标题是“Changes to be commited”。如果你现在提交的话,这个文件的版本就是你运行git add时的快照。git add命令会将一个路径名当成是一个文件或是目录;如果是一个目录,它会递归的将目录下的所有文件添加上。

临时存储修改过的文件(Staging Modified Files)

先修改一个已经被跟踪的文件。假设你修改了一个已被跟踪的叫做benchmarks.rb的文件,然后运行状态检查命令:

$ git status# On branch master# Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## new file: README## Changed but not updated:# (use "git add
..." to update what will be committed)## modified: benchmarks.rb#

 benchmarks.rb文件出现在“Changed but not updated”的段中-这意味着当前目录下被跟踪的文件已经被修改了但是还没有被临时存储(staged)。想要临时存储它,需要运行git add命令(它是一个多用途的命令-你使用它跟踪新文件,临时存储文件还有一些其他的事情如标记合并冲突的文件为resolved)。我们先运行git add命令临时存储benchmarks.rb文件,然后运行git status:

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

这两个文件都会在你下一次提交的时候被提交。这时,假设在你提交之前,你又想对benchmarks.rb进行一个小的变动,你打开它,做了那个修改,然后你准备提交。然而,我们再运行git status 看看是神马情况:

$ vim benchmarks.rb$ git status# On branch master# Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## new file: README# modified: benchmarks.rb## Changed but not updated:# (use "git add
..." to update what will be committed)## modified: benchmarks.rb#

见鬼了?现在benchmarks.rb既出现在了临时存储(staged)的文件中也出现在了未临时存储(unstaged)中。这肿么可能呢?事实上,当你运行git add 的时候Git确实是已经临时存储(staged)了这个文件。如果你现在提交的话,benchmarks.rb的版本将会是你上次运行git add时候的版本,而不是现在的在你工作目录里的那个版本。如果在你运行git add某个文件之后又修改了这个文件,你必须再运行git add来将最新版本的文件临时存储。

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

忽略文件(Ignoring Files)

 通常有些类别的文件你不想让Git自动添加到临时存储里,或者是作为untracked的文件。这些文件通常都是自动生成的比如日志文件或者是一些由你的系统自己生成的。在这种情况下,你可以创建一个列出一些模式/正则的文件来匹配它们,这个文件被命名为.gitignore。一个.gitignore的例子:

$ cat .gitignore*.[oa]*~

第一行告诉Git忽略;以.o和.a结尾的任何文件--构建你的代码的对象或者存档文件。第二行告诉Git忽略那些以波浪线结尾的文件,这写文件可能是文本编辑器标记的临时文件。你也可能包括一些log,tmp,或者pid目录;自动生成的文件等等。在你开始之前就设置后.gitignore文件通常都是一个好的idea,这样的话,你就不会无意间提交一些你不希望出现在你Git库里的文件。

在.gitignore文件里的匹配模式规则如下:

1、空白行或者以#开始的行会被忽略

2、可以使用标准的匹配模式

3、可以用一个斜杠(/)指定一个目录

4、可以通过感叹号(!)取消一个模式,感叹号在开头

标准的匹配模式就像是shell使用的简化的正则表达式一样。星号(*)匹配零个或多个字符;[abc]匹配括号里的任何字符(此例中是a,b或c);一个问号匹配一个字符;中括号里的[0-9]匹配它们里面的任意一个字符(此例中是0-9)。

.gitignore的另一个例子:

# a comment - this is ignored*.a       # no .a files!lib.a    # but do track lib.a, even though you're ignoring .a files above/TODO     # only ignore the root TODO file, not subdir/TODObuild/    # ignore all files in the build/ directorydoc/*.txt # ignore doc/notes.txt, but not doc/server/arch.txt

 查看你临时存储与未存储的变化

如果git status命令得到的信息对你来说太含糊了-你想要确切的知道你修改了什么,而不仅仅是你修改了那个文件-你可以使用git diff命令。稍后详细介绍git diff命令;你最常使用它的原因是为了解决这样两个问题:哪些东西你修改了但是还没有临时存储(staged);哪些东西你已经临时存储了下一步打算提交。尽管git status通常能够解决这两个问题,git diff能够确切的告诉你哪行添加了或者删除了-它就是一个补丁,一直都是这样-.-!。

假设你再次编辑并且临时存储(stage,往后叫缓存吧)了README文件,然后编辑了benchmards.rb文件而没有缓存它。如果你运行git status命令,u'll c:

$ git status# On branch master# Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## new file: README## Changed but not updated:# (use "git add
..." to update what will be committed)## modified: benchmarks.rb#

 想要查看你修改的但是没有缓存的文件,直接输入git diff没有参数:

$ git diffdiff --git a/benchmarks.rb b/benchmarks.rbindex 3cb747f..da65585 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -36,6 +36,10 @@ def main           @commit.parents[0].parents[0].parents[0]         end+        run_code(x, 'commits 1') do+          git.commits.size+        end+         run_code(x, 'commits 2') do           log = git.commits('master', 15)           log.size

 这个命令比较在你工作目录里与在缓存区域的文件。你看到的是你未缓存修改的与缓存的文件之间的变化。

如果你想查看下一次将要提交的在缓存区里的改变,可以使用git diff --catched。(Git 1.6.1版本以及之后版本,可以使用git diff --staged,这个可能更容易记吧)。这个命令将会比较缓存里的文件与你上一次提交的文件之间的差异。

$ git diff --cacheddiff --git a/README b/READMEnew file mode 100644index 0000000..03902a1--- /dev/null+++ b/README2@@ -0,0 +1,5 @@+grit+ by Tom Preston-Werner, Chris Wanstrath+ http://github.com/mojombo/grit++Grit is a Ruby library for extracting information from a Git repository

 注意 git diff 自己并不会告诉你从你上次提交至今所有的变化-它只告诉你那些你未缓存的修改。这可能会让人产生疑惑,因为你已经将你所有的修改都缓存(staged)了,git diff 却什么也没输出。

另一个例子,如果你缓存了benchmarks.rb文件,然后编辑它了,你可以使用 git status 查看缓存和未缓存之间的变化:

$ git add benchmarks.rb$ echo '# test line' >> benchmarks.rb$ git status# On branch master## Changes to be committed:##	modified:   benchmarks.rb## Changed but not updated:##	modified:   benchmarks.rb#

 可以使用 git diff 查看未缓存的修改:

$ git diffdiff --git a/benchmarks.rb b/benchmarks.rbindex e445e28..86b2f7c 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -127,3 +127,4 @@ end main() ##pp Grit::GitRuby.cache_client.stats+# test line

 使用 git diff --cached 查看到目前为止你已经缓存的变化:

$ git diff --cacheddiff --git a/benchmarks.rb b/benchmarks.rbindex 3cb747f..e445e28 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -36,6 +36,10 @@ def main          @commit.parents[0].parents[0].parents[0]        end+        run_code(x, 'commits 1') do+          git.commits.size+        end+        run_code(x, 'commits 2') do          log = git.commits('master', 15)          log.size

 提交修改

既然你的缓冲区(临时存储区,staging area)已经如你所愿的建好了,接下来就可以提交修改了。请记住,任何未缓存(unstaged)的东西-任何你已经创建或者修改但是还没有运行 git add 命令添加到缓冲区的文件-这次都不会提交。在你的硬盘上它们仍然保持修改(modified)的状态。在这种情况下,最后一次你运行 git status ,你会看到你所缓存的任何文件,然后你才会提交修改。提交的最简单的方式就是 git commit:

$ git commit

这样做之后将会加载你选择的文本编辑器。(这是由shell的$EDITOR环境变量指定的,通常是vim或emacs,然而你也可以通过git config --gloable core.editor命令配置它)。

文本显示下面的文字(vim 示例)

# Please enter the commit message for your changes. Lines starting# with '#' will be ignored, and an empty message aborts the commit.# On branch master# Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## new file: README# modified: benchmarks.rb~~~".git/COMMIT_EDITMSG" 10L, 283C

默认的提交信息包括最新的 git status 命令的输出以及一个顶部空行。 你可以删除这些注释输入自己的提交信息,你也可以留它们在那帮你回忆你提交的信息。(如果你想要更详细的信息提醒你你修改了些什么,你可以给 git commit 加上 -v 选项。这么做会将 git diff 的信息添加上去)。当你退出编辑器的时候,Git会将提交信息添加到你的提交里。(注释与diff的信息会被删除)。

你也可以直接在命令行上添加提交信息,通过在 git command 之后添加 -m标记,然后在其后添加信息:

$ git commit -m "Story 182: Fix benchmarks for speed"[master]: created 463dc4f: "Fix benchmarks for speed" 2 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 README

这是你的第一次提交!你会看到这次提交会告诉你一些它自己的信息:你提交到哪个分支(master),这次提交的SHA-1校验码(463dc4f),多少文件被修改了,以及多少行添加了,删除了。

这次提交记录了你建立的缓存区的的快照。任何你未缓存的仍然是修改状态。每次你提交,你都是在记录你工程的快照,你可以恢复它或者与之后的版本做比较。

 跳过缓冲区(Skipping the Staging Area)

尽管能够编辑你想要的提交信息是很有用的,但是有时在你的工作中这对于你的需求来说有点复杂。如果你想要跳过缓存区,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(-)

注意在这个例子里,提交之前你不必对 benchmarks.rb 运行 git add 命令。

移除文件

从Git里移除一个文件,你必须从你跟踪的文件里移除它(更确切点说,从你的缓存区里移除它)然后提交。git rm 命令就是干这事的,并且它会从你工作目录里移除这个文件,这样下次就不会看到为跟踪的文件了。

如果你只是从你的工作目录里移除了这个文件, 运行 git status,这个文件将会出现在 Changed but not updated域下。(也就是说,未缓存的 unstaged)

$ rm grit.gemspec$ git status# On branch master## Changed but not updated:#   (use "git add/rm 
..." 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 
..." to unstage)## deleted: grit.gemspec#

下一次提交,这个文件将会消失,并且不再会被跟踪。如果你修改了这个文件,并且已经把它添加到了索引里。你必须使用 -f 选项强制删除它。 这是一个安全的特性,它将阻止那些还没有记录到快照里的数据的意外删除,这能防止从Git里不能恢复文件。(大白话:if 缓冲区文件 == 磁盘文件 git rm;缓冲区文件 != 磁盘文件 git rm -f)

还有,你可能想要保持你的文件在工作目录里,但是从你的缓存区里移除它。换句话说,你想要这个文件在你的硬盘上,但是不让Git跟踪它。当你忘了往 .gitignore 里添加点神马的时候,所以你就会在无意间将这些文件缓存了,比如一个很大的日志文件,或者一堆 .a 编译过的文件,这时这个功能就会非常有用,通过使用 --cached 选项:

$ git rm --cached readme.txt

可以向 git rm 传递文件,目录,文件通配符。也就是你可以这样做:

$ git rm log/\*.log
注意 "*" 之前的 反斜杠(/).这是必须的,因为除了shell的文件名展开之外,Git有它自己的文件名展开方式。这个命令移除了在log/目录下所有以 .log 为扩展的文件。或者,你也可以这样做:
$ git rm \*~
这个命令移除所有以“~”结尾的文件。

移动文件

与其他CVS系统不同,Git并不明确跟踪文件的移动。如果你在GIt里重命名了一个文件,在Git里将不会存储那种你重命名了这个文件的元数据。然而,当你明白实际情况之后,你就会发现Git很聪明-之后详述。

Git 竟然有一个 mv 的命令,你可能会感到困惑。如果你想在Git里重命名一个文件,这么做:

$ git mv file_from file_to

这很好。事实上,如果你这么做了,那么你看一下它的状态,你会发现,Git将它看作是一个重命名的文件:

$ git mv README.txt README$ git status# On branch master# Your branch is ahead of 'origin/master' by 1 commit.## Changes to be committed:#   (use "git reset HEAD 
..." to unstage)## renamed: README.txt -> README#

 然而,这与下面的命令是一样的:

$ mv README.txt README$ git rm README.txt$ git add README

 Git 暗地里(implicitly)会将它看成是一个重命名,所以重命名使用那种方式都一样。唯一的不同是 mv 是一个命令 而不是三个-这是个很方便的功能。更重要的是,你可以使用任何工具重命名一个文件,之后在提交之前使用add/rm。

<TBC>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/orion/blog/23567

你可能感兴趣的文章
Swift对象转为C指针
查看>>
Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)
查看>>
ThinkSNS系统升级,版本多样化
查看>>
ecshop使用smtp发送邮件
查看>>
RubyInstaller
查看>>
21. SQL -- TSQL架构,系统数据库,文件,SQL 认证,TSQL语句
查看>>
CentOS6.0添加163和epel源
查看>>
使用组策略与脚本发布Office 2010
查看>>
Open××× 分配固定IP
查看>>
elk+redis centos6.6安装与配置
查看>>
linux下svn命令大全
查看>>
windows server 2008 在vm上安装
查看>>
我的友情链接
查看>>
谷果等手机刷机build.prop解析
查看>>
Vbox虚拟机下 Linux网络配置
查看>>
Vmware vsphere知识中易混淆和忽略的多个概念
查看>>
Android客户端和服务端如何使用Token和Session
查看>>
Python Pycharm导入第三方包
查看>>
Nginx源码安装
查看>>
我的友情链接
查看>>