# 参考手册

2022年9月13日15分钟阅读

- FormalSciences/ComputerScience
- GettingStarted/VersionControl
- Git/Advanced

## 创建与克隆项目

有两种方式获取一个 Git 仓库，仓库是 Git 存放你要保存的快照的数据的地方。

- 初始化一个新的 Git 仓库。
- 克隆一个存在的项目。

### Git Init

在命令行当前目录中执行 git init，就可以将当前目录初始化为 Git 仓库。

    $ ls -l
    total 0
    $ git init
    Initialized empty Git repository in /root/gitStudy/.git/
    # 在 /root/gitStudy/.git/ 目录初始化空 Git 仓库完毕。
    $ ls -a
    .  ..  .git

### Git Clone

如果需要克隆一个存在的项目。，在命令行当前目录中执行 git clone [url]，url 为项目地址，然后就可以了。git clone 实际上是一个封装了其他几个命令的命令。

1. 它创建了一个新目录，切换到新的目录。
2. 然后 git init 来初始化一个空的 Git 仓库， 然后为你指定的 URL 添加一个（默认名称为 origin 的）远程仓库。
3. 再针对远程仓库执行 git fetch，最后通过 git checkout 将远程仓库的最新提交检出到本地的工作目录。

    $ git clone git://github.com/schacon/simplegit.git
    Initialized empty Git repository in /private/tmp/simplegit/.git/
    remote: Counting objects: 100, done.
    remote: Compressing objects: 100% (86/86), done.
    remote: Total 100 (delta 35), reused 0 (delta 0)
    Receiving objects: 100% (100/100), 9.51 KiB, done.
    Resolving deltas: 100% (35/35), done.
    $ cd simplegit/
    $ ls
    README   Rakefile lib

## 快照基础

Git 的工作就是创建和保存项目的快照，及与之后的快照进行对比。

简而言之，使用 git add 添加需要追踪的新文件和待提交的更改， 然后使用 git status 和 git diff 查看有何改动， 最后用 git commit 将你的快照记录。绝大部分时候的基本流程都是这样的。

### Git Add

在 Git 中提交修改文件之前，需要将它们添加到缓存。

    # 添加 helloworld.cpp 至缓存区
    $ git add helloworld.cpp
    # 添加当前目录至缓存区
    $ git add .

### Git Status

在 Git 中执行 git status 命令，查看代码在缓存与当前工作目录的状态。

    # 简短输出
    $ git status -s
    # 详细输出
    $ git status

### Git Diff

在 Git 中使用 git diff 描述已临时提交的或者已修改但尚未提交的改动。

    # 尚未缓存的改动
    $ git diff
    # 查看已缓存的改动
    $ git diff --cached
    # 查看已缓存的与未缓存的所有改动
    $ git diff HEAD
    # 显示摘要而非整个 diff
    $ git diff --stat

### Git Commit

在 Git 中使用 git add 将内容写入缓存，然后执行 git commit 就将它实际存储快照了。

    # 配置提交信息
    $ git config --global user.name 'Your Name'
    $ git config --global user.email you@somedomain.com
    # 添加至缓存
    $ git add hello.rb
    # 输出状态摘要
    $ git status -s
    M  hello.rb
    # 提交快照
    $ git commit -m 'my hola mundo changes'
    [master 68aa034] my hola mundo changes
     1 files changed, 2 insertions(+), 1 deletions(-)
    # 使用 -S 标志提交签名加密
    $ git commit -S -m 'my hola mundo changes'
    # 撤销上次提交
    $ git commit --amend

如果执行 git commit 不适用 -m 选项，Git 则会尝试打开一个编辑器以填写提交信息。如果认为使用 git add 提交的流程太过繁琐，Git 允许使用 -a 选项跳过这一步。

    $ vim hello.rb
    $ git status -s
     M  hello.rb
    $ git commit -m 'changes to hello file'
    # On branch master
    # Changed but not updated:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    # modified:   hello.rb
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    $ git commit -am 'changes to hello file'
    [master 78b2670] changes to hello file
     1 files changed, 2 insertions(+), 1 deletions(-)

### Git Reset HEAD

git reset 命令用于回退版本，可以指定退回某一次提交的版本。

    $git reset HEAD^

### Git Rm

通过执行 git rm 来删除 Git 追踪的文件，它还会删除你的工作目录中的相应文件。

### Git Mv

git mv 命令是一个便利命令，用于移到一个文件并且在新文件上执行 git add 命令及在老文件上执行 git

rm 命令。

### Git Clean

git clean 是一个用来从工作区中移除不想要的文件的命令。 可以是编译的临时文件或者合并冲突的文件。

## 分支与合并

几乎每一种版本控制系统都以某种形式支持分支，一个分支代表一条独立的开发线。使用分支意味着你可以从开发主线上分离开来，然后在不影响主线的同时继续工作。Git 的分支模型称为必杀技特性，而正是因为它，将 Git 从版本控制系统家族里区分出来。

### Git Branch

在 Git 中列出、创建与管理工作上下文。

    # 列出可用的分支
    $ git branch
    # 创建新分支
    $ git branch (branchname)
    # 删除分支
    $ git branch -d (branchname)

### Git Switch

在 Git 中切换至指定分支。

    $git switch master

### Git Checkout

在 Git 中 git checkout 创建新分支，并立即切换到它

    $git checkout -b (branchname)

### Git Merge

一旦某分支有了独立内容，你终究会希望将它合并回到你的主分支。 你可以使用 `git merge` 命令将任何分支合并到当前分支中去。

    $ git branch
    * master
      removals
    $ ls
    README   hello.rb more.txt test.txt
    $ git merge removals
    Updating 8bd6d8b..8f7c949
    Fast-forward
     more.txt |    1 -
     test.txt |    1 -
     2 files changed, 0 insertions(+), 2 deletions(-)
     delete mode 100644 more.txt
     delete mode 100644 test.txt
    $ ls
    README   hello.rb

### Git Stash

git stash 命令用来临时地保存一些还没有提交的工作，以便在分支上不需要提交未完成工作就可以清理工作

目录。

### Git Log

在使用 Git 提交了若干更新之后，又或者克隆了某个项目，想回顾下提交历史，我们可以使用 git log 命令查看。

    $ git log
    commit 8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d
    Merge: 3cbb6aa 3ac015d
    Author: Scott Chacon <schacon@gmail.com>
    Date:   Fri Jun 4 12:59:47 2010 +0200

        Merge branch 'fix_readme'

        Conflicts:
            README

    commit 3cbb6aae5c0cbd711c098e113ae436801371c95e
    Author: Scott Chacon <schacon@gmail.com>
    Date:   Fri Jun 4 12:58:53 2010 +0200

        fixed readme title differently

    ...

### Git Tag

如果你达到一个重要的阶段，并希望永远记住那个特别的提交快照，你可以使用 `git tag` 给它打上标签。

    $ git tag -a v1.0
    # 指定提交打标签
    $ git tag -a v0.9 558151a
    # 指定标签信息命令
    $ git tag -a <tagname> -m "runoob.com标签"
    # PGP签名标签命令
    $ git tag -s <tagname> -m "runoob.com标签"

## 项目分享与更新

Git 并不像 Subversion 那样有个中心服务器。 目前为止所有的命令都是本地执行的，更新的知识本地的数据库。简而言之使用 git fetch 更新你的项目，使用 git push 分享你的改动。 你可以用 git remote 管理你的远程仓库。

### Git Remote

在 Git 中 git remote 命令管理远端仓库列表。

    # 列出远端别名
    $ git remote
    # 为项目添加一个新的远端仓库
    $ git remote add <remote-name>
    # 删除现存的某个别名
    $ git remote rm <remote-name>

### Git Fetch

在 Git 中 git fetch 从远端仓库下载新分支与数据。

    $git fetch <remote-name>

### Git Pull

在 Git 中 **git pull 从远端仓库提取数据并尝试合并到当前分支。**该命令就是在 git fetch 之后紧接着 git merge 远端分支到你所在的任意分支。

    $git pull <remote-name>

### Git Push

在 Git 中 git push remote-name branch-name 将本地改动推送到远端仓库。 如果可以的话，它会依据你的 branch 的样子，推送到远端的 branch 去。

    $git push github master

### Git Archive

git archive 命令用来创建项目一个指定快照的归档文件。

### Git Submodule

git submodule 命令用来管理一个仓库的其他外部仓库。

## 检查与比较

### Git Show

git show 命令可以以一种简单的人类可读的方式来显示一个 Git 对象。 一般使用此命令来显示一个标签或一

个提交的信息。

### Git Shortlog

git shortlog 是一个用来归纳 git log 的输出的命令。 它可以接受很多与 git log 相同的选项，但是此命

令并不会列出所有的提交，而是展示一个根据作者分组的提交记录的概括性信息

### Git Describe

git describe 命令用来接受任何可以解析成一个提交的东西，然后生成一个人类可读的字符串且不可变。

## 调试

### Git Bisect

git bisect 工具是一个非常有用的调试工具，它通过自动进行一个二分查找来找到哪一个特定的提交是导致

bug 或者问题的第一个提交。

### Git Blame

git blame 命令标注任何文件的行，指出文件的每一行的最后的变更的提交及谁是那一个提交的作者。 当你要

找那个人去询问关于这块特殊代码的信息时这会很有用。

### Git Grep

git grep 命令可以帮助在源代码中，甚至是你项目的老版本中的任意文件中查找任何字符串或者正则表达式。

## 补丁

### Git Cherry-pick

git cherry-pick 命令用来获得在单个提交中引入的变更，然后尝试将作为一个新的提交引入到你当前分支

上。 从一个分支单独一个或者两个提交而不是合并整个分支的所有变更是非常有用的。

### Git Rebase

git rebase 命令基本是是一个自动化的 cherry-pick 命令。 它计算出一系列的提交，然后再以它们在其他

地方以同样的顺序一个一个的 cherry-picks 出它们。

### Git Revert

git revert 命令本质上就是一个逆向的 git cherry-pick 操作。 它将你提交中的变更的以完全相反的方式

的应用到一个新创建的提交中，本质上就是撤销或者倒转。

## 邮件

### Git Apply

git apply 命令应用一个通过 git diff 或者甚至使用 GNU diff 命令创建的补丁。 它跟补丁命令做了差不多

的工作，但还是有一些小小的差别。

### Git Am

git am 命令用来应用来自邮箱的补丁。特别是那些被 mbox 格式化过的。 这对于通过邮件接受补丁并将他们

轻松地应用到你的项目中很有用。

### Git Format-patch

git format-patch 命令用来以 mbox 的格式来生成一系列的补丁以便你可以发送到一个邮件列表中。

### Git Imap-send

git imap-send 将一个由 git format-patch 生成的邮箱上传至 IMAP 草稿文件夹。

### Git Send-email

git send-mail 命令用来通过邮件发送那些使用 git format-patch 生成的补丁。

### Git Request-pull

git request-pull 命令只是简单的用来生成一个可通过邮件发送给某个人的示例信息体。 如果你在公共服务

器上有一个分支，并且想让别人知道如何集成这些变更，而不用通过邮件发送补丁，你就可以执行此命令的输出

发送给这个你想拉取变更的人。

## 外部系统

### Git Svn

git svn 可以使 Git 作为一个客户端来与 Subversion 版本控制系统通信。 这意味着你可以使用 Git 来检出内

容，或者提交到 Subversion 服务器。

### Git Fast-import

对于其他版本控制系统或者从其他任何的格式导入，你可以使用 git fast-import 快速地将其他格式映射到

Git 可以轻松记录的格式。

## 管理

### Git Gc

git gc 命令在你的仓库中执行 “garbage collection”，删除数据库中不需要的文件和将其他文件打包成一种

更有效的格式。

### Git Fsck

git fsck 命令用来检查内部数据库的问题或者不一致性。

### Git Reflog

git reflog 命令分析你所有分支的头指针的日志来查找出你在重写历史上可能丢失的提交。

### Git Filter-branch

git filter-branch 命令用来根据某些规则来重写大量的提交记录，例如从任何地方删除文件，或者通过过

滤一个仓库中的一个单独的子目录以提取出一个项目。