【Chapter 4】通过实际操作学习 Git

唉~我以为休息几天就不会痛了,看来我还是太天真了,实在是闲不住了,今天重新开始写笔记吧,读者们也注意身体,不要久坐。

第四章 通过实际操作学习 Git

4.1 基本操作

  • git init ——初始化仓库
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello (master)
    $ mkdir git-tutorial
    
    $ cd git-tutorial
    bash: cd: git-tutorial: No such file or directory
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (master)
    $ git init
    Initialized empty Git repository in C:/Users/76152/Desktop/PyProjects/GitHub/Hello/git-tutorial/.git/
    
    
    

    如果初始化成功了,执行了 git init 命令的目录下会生成 .git 目录。这个目录存储着管理当前目录内容所需的仓库数据

  • git status——查看仓库的状态
    $ git status
    On branch master
    
    Initial commit
    
    nothing to commit (create/copy files and use "git add" to track)
    
    

    结果显示了我们当前正处于 master 分支下,且没有可提交的内容。

    接着我们创建 README.md 文件作为管理对象,为第一次提交做前期准备。

    $ touch README.md
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (master)
    $ git status
    On branch master
    
    Initial commit
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            README.md
    
    nothing added to commit but untracked files present (use "git add" to track)
    

    可以看到在 Untracked files中显示了 README.md文件。

    类似地, 只要对 Git 的工作树或仓库进行操作,git status命令的显示结果就 会发生变化。

  • git add——向暂存区中添加文件
    $ git add README.md
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (master)
    $ git status
    On branch master
    
    Initial commit
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
            new file:   README.md
    
    

    将 README.md 文件加入暂存区后,使用 git status 命令查看 README.md 文件,显示结果已经变化。

  • git commit——保存仓库的历史记录

    git commit命令可以将当前暂存区中的文件实际保存到仓库的历 史记录中。通过这些记录,我们就可以在工作树中复原文件。

    1. 记述一行提交信息

    $ git commit -m "First commit"
    [master (root-commit) 51e40bb] First commit
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 README.md
    
    

    -m 参数后的 "First commit" 称作提交信息,是对这个提交的概述。

    2. 记述详细提交信息

    如果想要记述得更加详 细,请不加 -m,直接执行 git commit命令。

  • git log——查看提交日志
    $ git log
    commit 51e40bb0c4f7022a47f8cd0b1e1e58dde76ac9f5 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 15:39:19 2018 +0800
    
        First commit
    

    屏幕显示了刚刚的提交操作。 commit 栏旁边显示的 “51e40bb0c……” 是指向这个提交的哈希值。Git 的其他命令中,在指向提交时会用到这个哈希值。 最后就是该提交的提交信息。

    1. 只显示提交信息的第一行

    如果只想让程序显示第一行的简述性信息,可以在 git log 命令后加上 --pretty=short。

    $ git log --pretty=short
    commit 51e40bb0c4f7022a47f8cd0b1e1e58dde76ac9f5 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    
        First commit
    
    

    2. 只显示指定文件、目录的日志

    只要在 git log 命令后面加上目录名/文件名。便会显示相应的日志。

    $ git log README.md
    commit 51e40bb0c4f7022a47f8cd0b1e1e58dde76ac9f5 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 15:39:19 2018 +0800
    
        First commit
    

    3. 显示文件的改动

    如果想查看提交所带来的改动,可以加上 -p 参数,文件的前后差 别就会显示在提交信息之后。

    $ git log -p
    commit 51e40bb0c4f7022a47f8cd0b1e1e58dde76ac9f5 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 15:39:19 2018 +0800
    
        First commit
    
    diff --git a/README.md b/README.md
    new file mode 100644
    index 0000000..e69de29
    
    

    比如,我们修改 README.md,并执行下面的命令,就可以只查看 README.md 文件的提交日志以及提交前后的差别。

    $ git log -p README.md
    commit 95cf441aad40363e03326657aa25667a965078f9 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 16:03:56 2018 +0800
    
        text2
    
    diff --git a/README.md b/README.md
    index e69de29..f3ca610 100644
    --- a/README.md
    +++ b/README.md
    @@ -0,0 +1 @@
    +你好
    \ No newline at end of file
    
    commit 51e40bb0c4f7022a47f8cd0b1e1e58dde76ac9f5
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 15:39:19 2018 +0800
    
        First commit
    
    diff --git a/README.md b/README.md
    new file mode 100644
    index 0000000..e69de29
    :
    
  • git diff——查看更改前后的差别

    git diff命令可以查看工作树、暂存区、最新提交之间的差别。

    1. 查看工作树和暂存区的差别

    我们修改 README.md 文件,并执行 git diff 命令。

    $ git diff
    diff --git a/README.md b/README.md
    index e69de29..0d34868 100644
    --- a/README.md
    +++ b/README.md
    @@ -0,0 +1 @@
    +# Hello GitHub
    
    

    由于我们尚未用 git add 命令向暂存区添加任何东西,所以程序 只会显示工作树与最新提交状态之间的差别。

    “+”号标出的是新添加的行,被删除的 行则用“-”号标出。我们可以看到,这次只添加了一行。

    2. 查看工作树和最新提交的差别

    $ git add README.md
    
    $ git diff HEAD
    diff --git a/README.md b/README.md
    index 0d34868..4b4963b 100644
    --- a/README.md
    +++ b/README.md
    @@ -1 +1 @@
    -# Hello GitHub
    
    

    执行 git add README.md 后,如果现在执行 git diff命令,由于工作树和暂存区的状态并无 差别,结果什么都不会显示。要查看与最新提交的差别,请执行 git diff HEAD 命令。

    不妨养成这样一个好习惯:在执行 git commit 命令之前先执行 git diff HEAD命令,查看本次提交与上次提交之间有什么差别,等确认完毕后再进行提交。

    这里的 HEAD是指向当前分支中最新一次提交的指针。

    由于我们刚刚确认过两个提交之间的差别,所以直接运行git commit命令。

    $ git commit -m "Add index"
    [master 65f2814] Add index
     2 files changed, 1 insertion(+), 1 deletion(-)
     create mode 100644 test.txt
    
    

    保险起见,我们查看一下提交日志,确认提交是否成功。

    $ git log
    commit 65f2814a20db917f2d71457b3e5db95c377f4af9 (HEAD -> master)
    Author: Jadon <761529114@qq.com>
    Date:   Wed Apr 18 16:24:56 2018 +0800
    
        Add index
    
    

4.2 分支操作

在进行多个并行作业时,我们会用到分支。在这类并行开发的过程 中,往往同时存在多个最新代码状态。

如下图所示,从master分支创建 feature-A 分支和 fix-B 分支后,每个分支中都拥有自己的最新代码。master 分支是 Git 默认创建的分支,因此基本上所有开发都是以这个分支为中心进行的。

不同分支中,可以同时进行完全不同的作业。等该分支的作业完成之后再与 master 分支合并。比如 feature-A分支的作业结束后与 master 合并,如下图所示。

  • git branch——显示分支一览表

    git branch 命令可以将分支名列表显示,同时可以确认当前所在 分支。

  • git checkout -b——创建、切换分支

    如果想以当前的master分支为基础创建新的分支,我们需要用到 git checkout -b命令。

    1. 切换到 feature-A 分支并进行提交

    创建并切换到名为 feature-A 的分支

    $ git checkout -b feature-A
    Switched to a new branch 'feature-A'
    
    

    连续执行下面两条命令也能收到同样效果。

    $ git branch feature-A 
    $ git checkout feature-A
    

    使用 git branch 命令查看分支一览表, “ * ”表示我们当前的分支。

    $ git branch
    * feature-A
      master
    
    

    在这个状态下像正常开发那样修改代码、执行 git add 命令并进行提交的话,代码就会提交至 feature-A 分支。像这样不断对一个分支(例如 feature-A)进行提交的操作,我们称为“培育分支”。

    修改 README.md

    # Hello GitHub 
    
     - feature-A
    

    提交 README.md 到 feature-A 分支中。

    $ git add README.md
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (feature-A)
    $ git commit -m "Add feature-A"
    [feature-A f0adaa3] Add feature-A
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    

    2. 切换到 master 分支

    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (master)
    $ git checkout master
    Switched to branch 'master'
    

    打开文件 README.md ,发现文件并没有发生变化。

    feature-A分支的更改不会影响到 master分支,这正是在开发中创建分支的优点。

    3. 切换回上一个分支

    $ git checkout -
    Switched to branch 'feature-A'
    
    

    将“-”替换成 feature-A 同样可以切换到 feature-A 分支。

  • 特性分支

    特性分支顾名思义,是集中实现单一特性(主题),除此之外不进 行任何作业的分支。

    在日常开发中,往往会创建数个特性分支,同时在此之外再保留一个随时可以发布软件的稳定分支。稳定分支的角色通常 由 master 分支担当。

  • 主干分支

    主干分支是刚才我们讲解的特性分支的原点,同时也是合并的 点。

    通常人们会用 master 分支作为主干分支(拥有多个版本发布时,主干分支可以有多个)。主干分支中并没有开发到 一半的代码,可以随时供他人查看。

  • git merge——合并分支

    假设 feature-A 已经实现完毕,想要将它合并到主干分 支 master 中。

    首先切换到 master 分支。

    $ git checkout master
    Switched to branch 'master'
    
    

    然后合并 feature-A 分支。为了在历史记录中明确记录下本次分支合 并,我们需要创建合并提交。因此,在合并时加上 --no-ff参数。

    $ git merge --no-ff feature-A
    
    

    随后编辑器会启动,用于录入合并提交的信息。

    Merge branch 'feature-A'
    
    # Please enter a commit message to explain why this merge is necessary, 
    # especially if it merges an updated upstream into a topic branch. 
    #
    # Lines starting with '#' will be ignored, and an empty message aborts 
    # the commit.
    
    

    默认信息中已经包含了是从 feature-A 分支合并过来的相关内容,所 以可不必做任何更改。将编辑器中显示的内容保存,关闭编辑器,然后就会看到下面的结果。

    Merge made by the 'recursive' strategy.
    README.md | 2 ++ 
    1 file changed, 2 insertions(+)
    

    这样一来,feature-A 分支的内容就合并到 master 分支中了。

    注意:

    使用 git merge --no-ff feature-A 命令,会进入到vim 编辑器。

    然后你会发现编辑器里你怎么输入都没反应,这是因为vim处在不可编辑状态,按下字母键 c,此时进入编辑状态,可以开始修改注释信息了;

    再然后你会发现你怎么都退出不了,回到 shell 了,此时,按下 ESC 退出编辑状态;

    最后连续按两次大写字母键 Z,就可以保存信息并退出来了(第一次玩这个,折腾了挺久的)。

  • git log --graph——以图表形式查看分支

    用 git log --graph 命令进行查看的话,能很清楚地看到特性 分支(feature-A)提交的内容已被合并。

    除此以外,特性分支的创建 及合并也都清楚明了

    $ git log --graph
    *   commit a120a5cc58d1665b0b12793b92267a3f4f665491 (HEAD -> master)
    |\  Merge: 0fcf070 07f5b0a
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 17:43:07 2018 +0800
    | |
    | |     Merge branch 'feature-A'
    | |
    | * commit 07f5b0a0eb2598964c09082693749d201f905f7c (feature-A)
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 17:40:15 2018 +0800
    | |
    | |     Add feature-A
    | |
    | * commit ac3e358ca1848a6b1387d376acc3a008e3cb5172
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 17:27:42 2018 +0800
    | |
    | |     Add feature-A
    | |
    | * commit 34be8333a59d28ea692e002ff91eb55eed4398ff
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 17:20:46 2018 +0800
    | |
    
    

4.3 更改提交的操作

  • git reset——回溯历史版本

    Git的另一特征便是可以灵活操作历史版本。借助分散仓库的优势, 可以在不影响其他仓库的前提下对历史版本进行操作。

    为了让各位熟悉对历史版本的操作,我们先回溯历史版本,创建一个名为 fix-B 的特性分支。

1. 回溯到创建 feature-A 分支前

让我们先回溯到上一节feature-A分支创建之前,创建一个名为 fix-B 的特性分支。

要让仓库的HEAD、暂存区、当前工作树回溯到指定状态,需要用 到 git rest --hard命令。只要提供目标时间点的哈希值 A,就可以完全恢复至该时间点的状态。

$ git reset --hard 65f2814a20db917f2d71457b3e5db95c377f4af9
HEAD is now at 65f2814 Add index

我们已经成功回溯到特性分支(feature-A)创建之前的状态。由于所有文件都回溯到了指定哈希值对应的时间点上,README.md 文件的 内容也恢复到了当时的状态(只有标题的状态)。

2. 创建 fix-B 分支

$ git checkout -b fix-B
Switched to a new branch 'fix-B'

修改 README.md

Hello GitHub

- fix-B

提交文件

$ git add README.md

Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (fix-B)
$ git commit -m "Fix-B"
[fix-B dfa4302] Fix-B
 1 file changed, 3 insertions(+), 1 deletion(-)

现在的状态如图 4.5 所示。接下来我们的目标是图 4.6 中所示的状 态,即主干分支合并 feature-A 分支的修改后,又合并了 fix-B 的修改。

图4.5
图4.6

3. 推进至 feature-A 分支合并后的状态

首先恢复到 feature-A 分支合并后的状态。不妨称这一操作为“推进 历史”。(什么鬼?)

git log 命令只能查看以当前状态为终点的历史日志。

所以这里 要使用 git reflog 命令,查看当前仓库的操作日志。在日志中找出 回溯历史之前的哈希值,通过 git reset --hard 命令恢复到回溯历 史前的状态。

只要不进行 Git 的 GC(Garbage Collection,垃圾回收), 就可以通过日志随意调取近期的历史状态。

即便开发者错误执行了Git操作, 基本也都可以利用 git reflog 命令恢复到原先的状态。

$ git checkout -
Switched to branch 'master'

$ git reset --hard a120a5c
HEAD is now at a120a5c Merge branch 'feature-A'

当前状态为


  • 消除冲突

    现在只要合并 fix-B 分支,就可以得到我们想要的状态。

    $ git merge --no-ff fix-B
    Auto-merging README.md
    CONFLICT (content): Merge conflict in README.md
    Automatic merge failed; fix conflicts and then commit the result.
    
    

    这时,系统告诉我们 README.md 文件发生了冲突(Conflict)。

    系统在合并 README.md 文件时,feature-A 分支更改的部分与本次想要合并的 fix-B 分支更改的部分发生了冲突。

    不解决冲突就无法完成合并,所以我们打开 README.md文件,解决这个冲突。

    1.  查看冲突部分并将其解决

    此时打开 README.md 文件,就会发现内容变成了下面这个样子

    # Hello GitHub 
    
    <<<<<<< HEAD
     - feature-A
    =======
    - fix-B
    >>>>>>> fix-B
    
    

    =======以上的部分是当前HEAD的内容,以下的部分是要合并 的 fix-B 分支中的内容。我们在编辑器中将其改成想要的样子(直接改?我还以为有什么高端的操作)。

    # Hello GitHub 
    
     - feature-A
     - fix-B
    
    

    如上所示,本次修正让 feature-A 与 fix-B 的内容并存于文件之中。

    但是在实际的软件开发中,往往需要删除其中之一,所以各位在处理冲突时,务必要仔细分析冲突部分的内容后再行修改。

    2. 提交解决后的结果

    $ git add README.md
    
    $ git commit -m "Fix conflict"
    [master 51a829b] Fix conflict
    
    

  • git commit --amend——修改提交信息

    要修改上一条提交信息,可以使用 git commit --amend命令。

    我们将上一条提交信息记为了 "Fix conflict",但它其实是 fix-B分 支的合并,解决合并时发生的冲突只是过程之一,这样标记实在不妥。 于是,我们要修改这条提交信息。

    $ git commit --amend
     
    

    执行上面的命令后,编辑器就会启动。

    Fix conflict
    
    # 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^1 <file>..." to unstage) 
    # 
    #       modified:   README.md 
    #
    

    编辑器中显示的内容如上所示,其中包含之前的提交信息。

    请将 提交信息的部分修改为 Merge branch 'fix-B',然后保存文件,关闭编辑器(我也不知道是不是这样改,结果一样)。

    更改后

    $ git log --graph
    *   commit 2d9907ae4bc6efccdc647d181346794f65a4fa86 (HEAD -> master)
    |\  Merge: a120a5c dfa4302
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 20:26:32 2018 +0800
    | |
    | |     Merge branch 'fix-B'
    
    

  • git rebase -i——压缩历史

    在合并特性分支之前,如果发现已提交的内容中有些许拼写错误等, 不妨提交一个修改,然后将这个修改包含到前一个提交之中,压缩成一 个历史记录。这是个会经常用到的技巧,让我们来实际操作体会一下。

    1. 创建 feature-C 分支

    $ git checkout -b feature-C
    Switched to a new branch 'feature-C'
    
    

    修改文件,故意拼错

    # Hello GitHub 
    
     - feature-A
     - fix-B
     - faeture-C
    
    

    提交这部分内容。这个小小的变更就没必要先执行 git add命令 再执行 git commit命令了,我们用 git commit -am命令来一次 完成这两步操作。

    $ git commit -am "Add feature-C"
    [feature-C ae1dd4a] Add feature-C
     2 files changed, 1 insertion(+)
     delete mode 100644 test.txt
    
    

    2. 修正拼写错误

    自行修正 README.md 文件。

    修正后差别如下:

    $ git diff
    diff --git a/README.md b/README.md
    index 30e62c5..b77c703 100644
    --- a/README.md
    +++ b/README.md
    @@ -2,4 +2,4 @@
    
      - feature-A
      - fix-B
    - - faeture-C
    + - feature-C
    
    

    进行提交

    $ git commit -am "Fix typo"
    [feature-C 75b6433] Fix typo
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    

    错字漏字等失误称作 typo,所以我们将提交信息记为 "Fix typo"。

    实际上,我们不希望在历史记录中看到这类提交,因为健全的历史记录 并不需要它们。如果能在最初提交之前就发现并修正这些错误,也就不 会出现这类提交了。

    3. 更改历史

    将 "Fix typo"修正的内容与之前一次的提交合并,在历史记录中合并为一次完美的提交。为此,我们要用到 git rebase命令。

    $ git rebase -i HEAD~2
    

    用上述方式执行 git rebase命令,可以选定当前分支中包含 HEAD(最新提交)在内的两个最新历史记录为对象,并在编辑器中打开。


    如上所示,我们将 Fix typo 的 pick 改为 fixup,这样就可以把 Fix typo 的历史记录压缩到 Add feature-C 里。

    $ git rebase -i HEAD~2
    Successfully rebased and updated refs/heads/feature-C.
    
    

    系统显示 rebase 成功。也就是将 "Fix typo" 的内容合并到了上一个提交 "Add feature-C" 中,改写成了一个新的提交。

    $ git log --graph
    * commit 70e60670827b9c962a2532a421d4c01eb93c90b7 (HEAD -> feature-C)
    | Author: Jadon <761529114@qq.com>
    | Date:   Wed Apr 18 21:01:11 2018 +0800
    |
    |     Add feature-C
    |
    *   commit 2d9907ae4bc6efccdc647d181346794f65a4fa86 (master)
    |\  Merge: a120a5c dfa4302
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 20:26:32 2018 +0800
    | |
    | |     Merge branch 'fix-B'
    | |
    | * commit dfa4302d449eb325dae383a02e5e152723dbed26 (fix-B)
    | | Author: Jadon <761529114@qq.com>
    | | Date:   Wed Apr 18 19:53:59 2018 +0800
    | |
    | |     Fix-B
    
    

    这样一来,Fix typo 就从历史中被抹去,也就相当于 Add feature-C 中从来没有出现过拼写错误。这算是一种良性的历史改写。

    4.合并至 master 分支

    $ git checkout master
    Switched to branch 'master'
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Hello/git-tutorial (master)
    $ git merge --no-ff feature-C
    Merge made by the 'recursive' strategy.
     README.md | 1 +
     1 files changed, 1 insertion(+)
    
    

4.4 推送至远程仓库

Git 是分散型版本管理系统,但我们前面所学习的,都是针对单一 本地仓库的操作。下面,我们将开始接触远在网络另一头的远程仓库。

远程仓库顾名思义,是与我们本地仓库相对独立的另一个仓库。 让我们先在 GitHub 上创建一个仓库,并将其设置为本地仓库的远程仓库。

在 github 上新建一个名为 git-tutorial 的仓库,并且创建时请不要勾选 Initialize this repository with a README 选项。因为一旦勾 选该选项,GitHub一侧的仓库就会自动生成 README 文件,从创建之初便与本地仓库失去了整合性。

  • git remote add——添加远程仓库
    $ git remote add origin git@github.com:Jun-Dong/git-tutorial.git
    

  • git push——推送至远程仓库

    1. 推送至 master 分支

    使用 git push 将当前分支下本地库的内容推送给远程仓库。

    $ git push -u origin master
    Counting objects: 46, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (28/28), done.
    Writing objects: 100% (46/46), 3.82 KiB | 0 bytes/s, done.
    Total 46 (delta 7), reused 0 (delta 0)
    remote: Resolving deltas: 100% (7/7), done.
    To github.com:Jun-Dong/git-tutorial.git
     * [new branch]      master -> master
    Branch master set up to track remote branch master from origin.
    
    

    像这样执行 git push 命令,当前分支的内容就会被推送给远程仓库 origin 的 master 分支。-u参数可以在推送的同时,将 origin 仓库的 master 分支设置为本地仓库当前分支的 upstream(上游)。添加了这个参数,将来 运行 git pull 命令从远程仓库获取内容时,本地仓库的这个分支就可以直接从 origin 的 master 分支获取内容,省去了另外添加参数的麻烦。

    在 github 上可以确认远程 master 分支的内容是否和本地 master 分支相同。

    2. 推送至 master 以外的分支

    除了master分支之外,远程仓库也可以创建其他分支。举个例子,我们在本地仓库中创建 feature-D 分支,并将它以同名形式 push 至远程仓库。

    $ git checkout -b feature-D
    Switched to a new branch 'feature-D'
    
    $ git push -u origin feature-D
    Total 0 (delta 0), reused 0 (delta 0)
    To github.com:Jun-Dong/git-tutorial.git
     * [new branch]      feature-D -> feature-D
    Branch feature-D set up to track remote branch feature-D from origin.
    
    

    我们在本地仓库创建了 feature-D 分支,并将它 push 给远程仓库并保持分支名称不变。

    在 github 上查看 feature-D 分支。

4.5 从远程仓库获取

我们把在 GitHub 上新建的仓库设置成了远程仓库,并向 这个仓库push了 feature-D 分支。现在,所有能够访问这个远程仓库的 人都可以获取 feature-D 分支并加以修改。

接下来我们从实际开发者的角度出发,在另一个目录下新建一个本地仓库,学习从远程仓库获取内容的相关操作。这就相当于我们刚刚执行过 push 操作的目标仓库又有了另一名新开发者来共同开发。

  • git clone——获取远程仓库

    1. 获取远程仓库

    首先我们换到其他目录下,将 GitHub 上的仓库 clone 到本地。注意不要与之前操作的仓库在同一目录下。

    $ git clone git@github.com:Jun-Dong/git-tutorial.git
    Cloning into 'git-tutorial'...
    remote: Counting objects: 46, done.
    remote: Compressing objects: 100% (21/21), done.
    Receiving objects: 100% (46/46), done.
    Resolving deltas: 100% (7/7), done.
    remote: Total 46 (delta 7), reused 46 (delta 7), pack-reused 0
    
    Jadon@LAPTOP-QTBB80RR MINGW64 ~/Desktop/PyProjects/GitHub/Helo2
    $ cd git-tutorial
    
    

    执行 git clone 命令后我们会默认处于 master 分支下,同时系统会自动将 origin设 置成该远程仓库的标识符。也就是说,当前本地仓库 的 master 分支与 GitHub端远程仓库(origin)的 master分支在内容上是完全相同的。

    $ git branch -a
    * master
      remotes/origin/HEAD -> origin/master
      remotes/origin/feature-D
      remotes/origin/master
    
    

    我们用 git branch -a命令查看当前分支的相关信息。添加 -a 参数可以同时显示本地仓库和远程仓库的分支信息。

    2. 获取远程的 feature-D 分支

    $ git checkout -b feature-D origin/feature-D
    Switched to a new branch 'feature-D'
    Branch feature-D set up to track remote branch feature-D from origin.
    
    

    -b 参数的后面是本地仓库中新建分支的名称。为了便于理解,我们仍将其命名为 feature-D,让它与远程仓库的对应分支保持同名。新建分支名称后面是获取来源的分支名称。例子中指定了origin/feature-D, 就是说以名为 origin的仓库(这里指 GitHub 端的仓库)的 feature-D 分支为来源,在本地仓库中创建 feature-D 分支。

    3. 向本地的 feature-D 分支提交更改

    现在假定我们是另一名开发者,要做一个新的提交。在README. md 文件中添加一行文字,查看更改,并提交。

    $ git diff
    diff --git a/README.md b/README.md
    index b77c703..4309f62 100644
    --- a/README.md
    +++ b/README.md
    @@ -3,3 +3,4 @@
      - feature-A
      - fix-B
      - feature-C
    + - feature-D
    
    $ git commit -am "Add feature-D"
    [feature-D fe60f80] Add feature-D
     1 file changed, 1 insertion(+)
    
    

    4. 推送 feature-D 分支

    现在来推送 feature-D 分支

    $ git push
    Counting objects: 3, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 277 bytes | 0 bytes/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To github.com:Jun-Dong/git-tutorial.git
       4275a5a..fe60f80  feature-D -> feature-D
    
    

    从远程仓库获取 feature-D 分支,在本地仓库中提交更改,再将 feature-D 分支推送回远程仓库,通过这一系列操作,就可以与其他开发者相互合作,共同培育 feature-D 分支,实现某些功能。

  • git pull——获取最新的远程仓库分支

    现在回到原先的那个目录下,这边的本地仓库中只创建了 feature-D分支,并没有在 feature-D分支中进行任何提交。然而远程仓库的 feature-D 分支中已经有了我们刚刚推送的提交。 这时我们就可以使用 git pull 命令,将本地的 feature-D 分支更新到最新 状态。切换到 feature-D 分支。

    $ git pull origin feature-D
    remote: Counting objects: 3, done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
    Unpacking objects: 100% (3/3), done.
    From github.com:Jun-Dong/git-tutorial
     * branch            feature-D  -> FETCH_HEAD
       4275a5a..fe60f80  feature-D  -> origin/feature-D
    Updating 4275a5a..fe60f80
    Fast-forward
     README.md | 1 +
     1 file changed, 1 insertion(+)
    
    

    GitHub 端远程仓库中的 feature-D 分支是最新状态,所以本地仓库中的 feature-D 分支就得到了更新。今后只需要像平常一样在本地进行提交再push给远程仓库,就可以与其他开发者同时在同一个分支中进行作业,不断给 feature-D 增加新功能。

    如果两人同时修改了同一部分的源代码,push 时就很容易发生冲突。所以多名开发者在同一个分支中进行作业时,为减少冲突情况的发 生,建议更频繁地进行 push 和 pull 操作。

这一章有点长,今天就一章了哈。