Git常用命令教程

Git简介

Git 介绍

Git 是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git的读音为/gɪt/。GitLinus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

什么文件可以被 Git 管理?

文本文件(.txt),脚本文件(.py等),各种基于文本信息的文件.

什么文件不能被 Git 管理?

图片文件(.jpg等),PDF(.pdf),MS Word(.doc),MS Power Point(.ppt),MS Excel(.xls)等。

Git 基础

Git 直接记录快照,而非差异比较

Git 和其它版本控制系统(包括 Subversion 等)的主要差别在于 Git 对待数据的方法。 概念上来区分,其它大部分系统以文件变更列表的方式存储信息。 这类系统(CVSSubversionPerforceBazaar 等等)将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。
Git 不按照以上方式对待或保存数据。 反之,Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个「快照流」。
这是 Git 与几乎所有其它版本控制系统的重要区别。 因此 Git 重新考虑了以前每一代版本控制系统延续下来的诸多方面。Git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不只是一个简单的 VCS

Git 不需要联网就能工作

Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息,由于本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。而其他集中式版本控制系统(例如 SVN等),必须联网才能工作, 所有操作都有网络延时开销。

Git 保证完整性

Git 的内容完整性要优于其他集中式版本控制系统(例如 SVN等)。Git 中所有数据在存储前都计算校验和,然后以校验和来引用。这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若在传送过程中丢失信息或损坏文件,Git 就能发现。Git 用以计算校验和的机制叫做 SHA-1 哈希散列。 这是一个由40个十六进制字符(0-9a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:24b9da6552252987aa493b52f8696cd6d3b00373Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。

Git 一般只添加数据

Git 操作,几乎只往 Git 数据库中增加数据。 很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容;但是一旦你提交快照到 Git 中,就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。这使得在使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。

Git 安装

最早 Git 是在 Linux 上开发的,很长一段时间内,Git 也只能在 LinuxUnix 系统上跑。目前,Git 已经可以在 LinuxUnixMacWindows 几大平台上运行。详细的安装说明请前往 Git官网安装说明 查看, Git 在每种系统上的安装方式各不相同,安装步骤分别如下:

Linux平台上安装

打开 terminal,可以用下面的命令安装:

Debian/Ubuntu

1
$ apt-get install git-all

使用 git --version 查看是否安装成功

1
2
$ git --version
git version 2.7.4

Centos/RedHat

1
$ yum -y install git-all

使用 git --version 查看是否安装成功

1
2
$ git --version
git version 1.7.1

Mac 平台上安装

1、先下载 .dmg 安装包,下载地址为:https://git-scm.com/download/mac ,点击下载到本地,下载文件例如:git-2.14.1-intel-universal-mavericks.dmg
2、双击安装包进行安装即可
3、使用 git --version 查看是否安装成功

1
2
$ git --version
git version 2.14.1

Windows 平台上安装

1、先下载 .exe 安装包,下载地址为:https://git-scm.com/download/win ,选择适合当前系统的版本,点击下载到本地
2、双击安装包进行安装即可
3、在开始菜单里找到Git->Git Bash,会弹出 Git 命令窗口,使用 git --version 查看是否安装成功

1
2
$ git version
git version 2.14.2.windows.1

Git 配置

安装 Git 后,每台计算机上只需要进行一次配置,程序升级时会保留配置信息。你可以在任何时候再次通过运行命令来修改它们。
Git 自带一个 git config 的工具,专门用来配置或读取相应的工作环境变量。这些变量存储在三个不同的位置:

  • /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置,如果使用带有 --system 选项的 git config 时,它会从此文件读写配置变量。
  • ~/.gitconfig~/.config/git/config 文件:只针对当前用户,可以传递 --global 选项让 Git 读写此文件。
  • 当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。

每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。

Windows 系统中,Git 会查找 $HOME 目录下(一般情况下是 C:\Users\$USER)的 .gitconfig 文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。

配置用户信息

当安装完 Git 应该做的第一件事就是设置个人的「用户名称」与「邮件地址」。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:

1
2
$ git config --global user.name lichengjin
$ git config --global user.email lichengjin606@gmail.com

再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情,Git 都会使用那些信息。当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global选项的命令来配置,新的设定保存在当前项目的 .git/config 文件里。

查看配置信息

要检查已有的配置信息,可以使用 git config --list 命令:

1
2
3
$ git config --list
user.name=lichengjin
user.email=lichengjin606@gmail.com

有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig~/.gitconfig),不过最终 Git 实际采用的是最后一个。
这些配置我们也可以在 ~/.gitconfig/etc/gitconfi 看到,如下所示:

1
$ vim ~/.gitconfig

显示内容如下所示:

1
2
3
[user]
name = lichengjin
email = lichengjin606@gmail.com

你可以通过输入 git config <key> 来检查 Git的某一项配置,例如:

1
2
$ git config user.name
lichengjin

Git 工作流程

Git 的工作流程如下:

  1. 克隆 Git 资源作为工作目录。
  2. 在克隆的资源上添加或修改文件。
  3. 如果其他人修改了,你可以更新资源。
  4. 在提交前查看修改。
  5. 提交修改。
  6. 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。

下图展示了 Git 的工作流程,图片来自菜鸟教程
Git 工作流程图

Git 工作区,暂存区和版本库

工作区:就是你在电脑里能看到的目录。是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
暂存区:英文叫stage, 或index。是一个文件,一般存放在 .git/index 中,保存了下次将提交的文件列表信息,有时候也被称作索引( index )。
版本库:版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被 Git 管理起来,每个文件的修改、删除,Git 都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以还原。工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库,是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
下面这个图展示了「工作区」、「暂存区」和「版本库」之间的关系,图片来自菜鸟教程
工作区、暂存区和版本库之间的关系
图中左侧为「工作区」,右侧为「版本库」。在「版本库」中标记为 index 的区域是「暂存区」(stageindex),标记为 master 的是 master 分支所代表的目录树。
图中我们可以看出此时 HEAD 实际是指向 master 分支的一个「游标」。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
图中的 objects 标识的区域为 Git 的「对象库」,实际位于 .git/objects 目录下,里面包含了创建的各种对象及内容。
当对「工作区」修改或新增的文件执行 git add 命令时,「暂存区」的目录树被更新,同时「工作区」修改或新增的文件内容被写入到「对象库」中的一个新的对象中,而该对象的 ID 被记录在暂存区的文件索引中。
当执行提交操作 git commit 时,「暂存区」的目录树写到「版本库」中,master 分支会做相应的更新。即 master 指向的目录树就是提交时「暂存区」的目录树。
当执行 git reset HEAD 命令时,「暂存区」的目录树会被重写,被 master 分支指向的目录树所替换,但是「工作区」不受影响。
当执行 git rm --cached <file> 命令时,会直接从「暂存区」删除文件,「工作区」则不做出改变。
当执行 git checkout . 或者 git checkout -- <file> 命令时,会用「暂存区」全部或指定的文件替换「工作区」的文件。这个操作很危险,会清除「工作区」中未添加到「暂存区」的改动。
当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换「暂存区」和以及「工作区」中的文件。这个命令也是极具危险性的,因为不但会清除「工作区」中未提交的改动,也会清除「暂存区」中未提交的改动。

获取版本库

创建新的版本库

1、 选择一个合适的地方,创建一个空目录:

1
2
3
4
$ mkdir git_tutorial
$ cd git_tutorial
$ pwd
/Users/lichengjin/workspace/git_tutorial

2、 通过 git init 命令把这个目录变成 Git 可以管理的仓库:
注:如果打算使用 Git 来对现有的项目进行管理,只需要进入该项目目录并输入git init

1
2
$ git init
Initialized empty Git repository in /Users/lichengjin/workspace/git_tutorial/.git/

该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干,是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
如果你没有看到 .git 目录,那是因为这个目录默认是隐藏的,用 ls -a 命令查看即可:

1
2
$ ls -a
. .. .git

克隆现有的版本库

如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone 命令。 如果你对其它的 VCS 系统(比如说 Subversion )很熟悉,请留心一下你所使用的命令是 clone 而不是 checkout。 这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。 当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。 事实上,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库(虽然可能会丢失某些服务器端的挂钩设置,但是所有版本的数据仍在)。

克隆仓库的命令格式:

1
git clone <repo>

例如:

1
git clone https://github.com/ChengjinLi/machine_learning.git

如果我们需要克隆到指定的目录,可以使用以下命令格式:

1
git clone <repo> <directory>

例如:

1
git clone https://github.com/ChengjinLi/machine_learning.git mj_machine_learning

参数说明:

  • repo:Git 仓库。
  • directory:本地目录。

Git 支持多种数据传输协议。 上面的例子使用的是 https:// 协议,不过你也可以使用 git:// 协议或者使用 SSH 传输协议。

Git 文件生命周期

请记住,「工作目录」下的每一个文件都不外乎这两种状态:「已跟踪」或「未跟踪」。「已跟踪」的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于「未修改」,「已修改」或「已放入暂存区」。 「工作目录」中除「已跟踪」文件以外的所有其它文件都属于「未跟踪」文件,它们既不存在于上次快照的记录中,也没有放入「暂存区」。 初次克隆某个仓库的时候,「工作目录」中的所有文件都属于「已跟踪」文件,并处于「未修改」状态。编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为「已修改」文件。 我们逐步将这些修改过的文件放入「暂存区」,然后提交所有暂存了的修改,如此反复。
使用 Git 时文件的生命周期如下:
Git 文件生命周期

Git 常用命令

git add <file_name>/<dir_name>
将文件添加到暂存区,参数可以是指定路径的文件名或目录的名字,也可以使用 glob 模式。

git status
查看项目的当前状态,输出详细内容
git status --shortgit status -s
查看项目的当前状态,以简短的结果输出
状态说明:

  • ?? 未跟踪的文件
  • M:修改过的文件,出现在靠左边的M表示该文件被修改了并放入了暂存区,出现在右边的M表示该文件被修改了但是还没放入暂存区,
  • A:新添加到暂存区的文件
  • D:已删除(deleted)
  • R:重命名(renamed)
  • C:已拷贝(copied)
  • U:已更新但为合并(updated but unmerged)

git diff
查看尚未 add 的所有文件的改动和上个已经 commit的文件的不同
git diff <file_name>
查看尚未 add<file_name> 文件的改动和上个已经 commit的文件的不同
git diff --cached
查看已经 add 的文件的改动
git diff HEAD
查看已 add 的与未 add 的所有改动
git diff --stat
显示摘要而非整个diff

git commit -m "message"
将暂存区的文件提交到版本库,-m后面输入的是本次提交的说明,可以输入任意内容,最好是有意义的,方便从历史记录找到改动记录。
git commit --amend --no-edit
将本次改动直接合并到上一个 commit
git commit -am "message"
跳过使用暂存区的方式,自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤。

git rm <file_name>/<dir_name>
将文件从暂存区域移除,参数可以是指定路径的文件名或目录的名字,也可以使用 glob 模式。
git rm --cached <file_name>/<dir_name>
将文件从 Git 仓库中删除,但仍然希望保留在当前工作目录中,参数可以是指定路径的文件名或目录的名字,也可以使用 glob 模式。

git mv <file_from> <file_to>
Git 中的 <file_from> 重命名为 <file_to>

git log
查看历史提交记录,显示从最近到最远的提交日志
git log --oneline
一行显示一次提交
git log --oneline --graph
查看历史中什么时候出现了分支、合并,开启了拓扑图选项
git log --author=<user_name>
查找指定用户 <user_name> 的提交日志

git reflog
查看历史命令记录,显示从最近到最远的日志

git reset HEAD
取消已缓存的内容,即取消之前 git add 添加的内容
Git 中,用 HEAD 表示当前版本,上一个版本就是 HEAD^ ,上上一个版本就是 HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成 HEAD~100
git reset <file_name>
取消已缓存的<file_name>,即取消之前 git add 添加的内容
git reset --hard <commit_id>
回退到指定 <commit_id> 版本,<commit_id>没必要写全,前位(例如前7位)就可以了,Git 会自动去找,当然也不能只写前一两位,因为 Git 可能会找到多个版本号,就无法确定是哪一个了。

git checkout <commid_id> -- <file_name>
<file_name> 回退到 <commid_id> 的版本
git checkout <branch_name>
HEAD 从当前分支切换到 <branch_name> 分支
git checkout -b <branch_name>
创建 <branch_name> 分支,并切换到新建的分支

git branch
查看当前分支,*代表了当前 HEAD 所在的分支
git branch <branch_name>
创建 <branch_name> 分支

git merge <branch_name>
<branch_name> 合并到当前分支,Git 会采用默认的 Fast forward 格式进行合并,这次合并操作不会有 commit 信息,log 中也不会有分支的图案。
git merge --no-diff -m "message" <branch_name>
采取 --no-ff 这种方式保留合并的 commit 信息。

忽略文件

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为.gitignore 的文件,列出要忽略的文件模式。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件 .gitignore 的格式规范如下:

  • 所有空行或者以 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号*匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号?只匹配一个任意字符;如果在方括号中使用短划线-分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有09的数字)。 使用两个星号*表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/za/b/c/z等。GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在 https://github.com/github/gitignore 找到它.

Github 使用

Github 是一个大家都积极贡献的地方, 你可以和各种人合作创作,也是开源的天堂, 只要你愿意, 任何人都能下载, 或修改你的杰作。
Github 上注册一个账户
然后添加一个 online 版本库 repository
连接本地版本库

1
git remote add [alias] [url]

例如:

1
2
$ git remote add origin https://github.com/ChengjinLi/machine_learning.git
$ git push -u origin master # 推送本地 master 去 origin

在执行 commit 之后,可以执行 git push -u origin master 将本地修改提交到 Github

要查看当前配置有哪些远程仓库,可以用命令:

1
2
$ git remote
origin

执行时加上 -v 参数,你还可以看到每个别名的实际链接地址。

1
2
3
$ git remote -v
origin https://github.com/ChengjinLi/machine_learning.git (fetch)
origin https://github.com/ChengjinLi/machine_learning.git (push)

删除别名为 <alias> 的远程仓库

1
$ git remote rm <alias>

相关链接

Git 官网: https://git-scm.com/
Git 完整命令手册地址: http://git-scm.com/docs
Pro Git book: https://git-scm.com/book/zh/v2
廖雪峰Git教程:
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
菜鸟Git教程: http://www.runoob.com/git/git-tutorial.html
Github 官网: https://github.com/

-------------本文结束感谢您的阅读-------------
坚持整理学习笔记,您的支持将鼓励我继续整理下去!