git_chapter2_基础

Chapter2 基础

参考自 https://git-scm.com/book/zh/v1/Git-%E5%9F%BA%E7%A1%80

2.1 获取项目的仓库

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

    如果要对本地的某个项目进行版本管理,只需要导航到项目所在目录,执行如下指令:

    $ git init
    

    执行完毕后,目录下会出现一个 .git 文件夹,所有 git 需要的数据和资源都保存在这个目录中。

    接下来,将项目中需要进行版本管理的文件纳入到 git 版本控制中:

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

    add 命令告诉 git, 该项目的那些文件需要被跟踪管理。commit 命令则是将文件暂存区的文件快照保存到本地数据库中。

  2. 从现有仓库克隆

    如果相对某个开源项目出份力,可以先把该项目的 git 仓库复制一份出来,这就需要用到 git clone 命令。注意,这跟 svn 的 checkout 不一样。 git clone 命令会克隆项目的所有历史数据(每一个文件的每一个版本),而 checkout 只是拉取服务器上项目的最新版本。

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

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

    这个命令执行后,会在当前目录下新建一个 grit 目录,其中包含一个 .git 目录,用于保存下载下来的所有版本记录,然后从中取出最新版本的文件拷贝。

2.2 把跟新记录到仓库

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

在编辑过某些文件之后,git 将这些文件标记为已修改。我们逐步把这些修改过的文件放到暂存区域,直到最后一次性提交所有这些暂存起来的文件,如此重复。

使用 git 时的文件状态变化周期如下图所示:

文件的状态变化周期
文件的状态变化周期

检查当前文件状态

使用 git status 命令可以查看哪些文件当前处于什么状态。

上一节我们 clone 了 grit 项目,在这个项目的根目录新建一个 README 文件。然后运行 git status 将会看到以下输出:

$ git status
On branch master
Your branch is up-to-date with 'origin/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)

在状态报告中可以看出 README 出现在 "Untracked files" 下面。表示 README 还没有被 git 跟踪。

跟踪新文件

使用 git add 命令可以跟踪一个新文件:

$ git add README

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   README

可以看到 README 的状态变成了 "Changes to be committed" 表示它变成了已暂存状态。如果此时提交,那么该文件此时此刻的版本将被留存到历史记录里。其实 git add 的潜台词就是把目标文件的快照放到已暂存区域,也就是 add file into staged area,这就好理解后续 add 操作的实际意义了。

暂存已修改文件

修改一下目录下 benchmarks.rb 文件,再用 git status 查看一下当前状态:

$ git status
On branch master
Your branch is up-to-date with 'origin/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 to be committed", 这说明已跟踪文件的内容发生了变化,但还没有放到暂存区。要把它放到暂存区的话,还是用之前的 git add 命令就好了,这个命令的执行效果和上一小节一样,就不展示了。

忽略某些文件

如果不希望某些文件纳入 git 的管理。可以在 根目录 创建一个名为 .gitignore 的文件,列出要忽略的文件模式。

  • 所有空行或者以注释符号 # 开头的行都会被 git 忽略;
  • 匹配模式最后跟反斜杠 (/) 说明要忽略的是目录;
  • 要忽略指定模式以外的文件或目录,可以在模式前加上感叹号 (!) 取反;
  • 可以使用标准 glob 模式匹配:
    • 星号 * 匹配零个或多个任意字符;
    • 问号 ? 只匹配一个任意字符;
    • [abc] 匹配方括号中的某个字符;
    • [0-9] 匹配所有 0 到 9 的数字;

下面是一个 .gitignore 文件的例子:

# 这行是注释

# 忽略所有 .a 结尾的文件
*.a

# 但 lib.a 除外
!lib.a

# 只忽略根目录下的 TODO.txt 文件,不包括子目录
/TODO.txt

# 会忽略 doc/*.txt 但不包括子目录
doc/*.txt

# 忽略 doc 目录下所有 *.txt 文件
doc/**/*.txt

# 忽略 build/ 目录下的所有文件
build/

查看具体修改

修改包括两方面:工作目录的修改(相对于暂存区);暂存区的修改(相对于仓库);

要显示工作目录与暂存区文件之间的差异,可以使用 git diff 命令:

$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 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 --staged(或者用旧版 git diff --cached):

$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 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 commit

上述会唤起编辑器来让你输入提交日志。也可以在后面加上 -m 参数写上简单日志:

$ git commit -m "some log text"

git commit 会将暂存区中的文件提交到仓库中。如果想要省略 git add 直接把工作目录的文件修改提交到仓库,可以使用 -a 选项:

$ git commit -a -m "skip git add"

移除文件

从仓库中移除一个文件,或者说不再跟踪某个文件,需要两个步骤:

  1. 将文件从暂存区中移除,使用 git rm 命令,这个文件会从工作目录中删除,并不再被 Git 跟踪;

  2. 将移除操作提交到仓库,使用 git commit 命令;

    $ git mv file_from file_to
    

    实际上它相当于

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

如果不想删掉工作目录中的文件,仅是移除 git 对文件的跟踪,可以使用 --cached 选项:

$ git rm --cached readme.txt

git rm 指令后面也可以接 glob 模式匹配,下述指令将删除 log/ 目录下所有 .log 文件:

$ git rm log/\*.log

移动文件

要进行文件移动操作,使用如下命令:

$ git mv file_from file_to

实际上它相当于

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

2.3 查看提交历史

提交了若干更新后,可以用 git log 命令查看,它还有一些有空的选项,具体可以参考 原文

除了使用 git log 指令,还可以在 bash 里输入 gitk, 打开 gitk 可视化工具来查看。

2.4 撤销操作

这一节介绍撤销操作相关的命令。

撤销最后一次提交

有的时候提交完了才发现有些文件没有提交,或者提交信息写错了。想要重写刚刚的提交操作,可以使用 --amend 选项来重新提交:

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

如上,第一次提交时忘记了一个文件,通过 git add 加上那个文件之后,再次使用 --amend 来提交。这样做的话最后只会产生一次提交,并且你有机会重写提交日志。

取消已经暂存的文件

如果不小心执行了 git add 命令,把不想提交的代码也提交到了暂存区,这个时候可以看一下 git status 中给出的恢复提示:

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

        modified:   README.txt
        modified:   benchmarks.rb

如上,根据提示,只要执行 git reset HEAD <file> 命令,就可以取消已经暂存的文件。

取消对文件的修改

如果修改了工作目录中的文件,想会退到未修改之前的状态,这个时候可以看一下 git status 给出的提示:

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

如上,根据提示,只要执行 git checkout -- <file> 命令,就可以会退到未修改时的版本。

2.5 远程仓库的使用

远程仓库是指托管在网络上的项目仓库,关于这部分的知识还没有理解透彻,这里先记下操作方法,在实践中继续领会。

查看当前的远程仓库:

要查看当前配置有哪些远程仓库,可以使用 git remote 命令。它会列出每个远程仓库的名字:

$ git clone git://github.com/schacon/ticgit.git
Cloning into 'ticgit'...
remote: Reusing existing pack: 1857, done.
remote: Total 1857 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1857/1857), 374.35 KiB | 193.00 KiB/s, done.
Resolving deltas: 100% (772/772), done.
Checking connectivity... done.
$ cd ticgit
$ git remote
origin

git remote -v 可以显示出对应的地址:

$ git remote -v
origin  git://github.com/schacon/ticgit.git (fetch)
origin  git://github.com/schacon/ticgit.git (push)

添加远程仓库

要添加一个新的远程仓库,使用 git remote add [shortname] [url] 命令,其中的 shortname 是为远程仓库取的别名。

$ git remote
origin
$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin  git://github.com/schacon/ticgit.git
pb  git://github.com/paulboone/ticgit.git

抓取远程仓库中的数据

上述指令只是将远程仓库的 url 存在了本地,并为它取了一个别名,并没有拉取仓库的数据。要拉取数据,使用 git fetch [shortname] 指令:

$ git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit

可以看到, pb 仓库里有两个新分支, master 和 ticgit.

需要注意的是 fetch 命令只是将远程仓库中的数据拉取到本地,并不会自动合并到当前工作分支(也就是说只是把数据存到了本地仓库里,并没有把数据提取到工作目录中)。

如果设置了某个分支用于跟踪某个远程仓库的分支。可以使用 git pull 命令抓取数据,并将数据合并到本地仓库的当前分支。实际上,默认情况下 git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录的当前分支。

推送数据到远程仓库

要将本地仓库中的数据推送到远程仓库,可以使用 git push [remote-name] [branch-name]。如果我们要把本地的 master 分支推动到 origin 服务器上,可以使用如下命令:

$ git push origin master

查看远程仓库信息

你可以使用 git remote show [remote-name] 命令来查看某个远程仓库的信息。

$ git remote show origin
* remote origin
  URL: git://github.com/schacon/ticgit.git
  Remote branch merged with 'git pull' while on branch master
    master
  Tracked remote branches
    master
    ticgit

远程仓库的删除和重命名

使用 git remote rename 可以修改远程仓库的别名:

$ git remote rename pb paul
$ git remote
origin
paul

使用 git remote rm 命令可以移除不需要的远程仓库:

$ git remote rm paul
$ git remote
origin

2.6 打标签

显示已有标签

使用 git tag 可以显示已有的标签:

$ git tag
v0.1
v1.3

新建标签

Git 使用的标签有两种类型:轻量级的(lightweight) 和 含附注的(annotated)。我们一般推荐后者,因为它能够携带更详细的信息。

含附注的标签

要创建含附注的标签,只需要加上 -a 参数即可:

$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4

轻量级标签

直接输入标签名,即可创建轻量级标签:

$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容