How to use Git

版本控制

版本控制就是控制版本,版本控制系统帮助控制(管理)某个事物(通常指源代码)的不同版本 现在流行的版本控制:

  • git
  • Subversion
  • Mercurial 版本控制系统分为两个类别:Centralized and Distributed (集中式模型和分布式模型)

版本控制系统的主要目的是帮助你保留项目的详细历史记录,并且能够在不同的版本上进行工作。保留详细的项目历史记录很重要,因为这样可以看出一段时间内项目的进度。如果需要,你还可以回到项目的某个阶段,并恢复数据或文件。

版本控制术语
  • 提交(Commit) Git 将数据看做微型文件系统的一组快照。每次 commit(在 Git 中保持项目状态),它都对文件当时的状况拍照,并存储对该快照的引用。你可以将其看做游戏中的保存点,它会保存项目的文件和关于文件的所有信息。
  • 仓库(Repository / repo) 仓库是一个包含项目内容以及几个文件(在 Mac OS X 上默认地处于隐藏状态)的目录,用来与 Git 进行通信。仓库可以存储在本地,或作为远程副本存储在其他计算机上。仓库是由 commit 构成的。
  • 工作目录 / 工作区(Working Directory) 工作目录是你在计算机的文件系统中看到的文件。当你在代码编辑器中打开项目文件时,你是在工作目录中处理文件
  • 检出(Checkout) 检出是指将仓库中的内容复制到工作目录下。
  • 暂存区 / 暂存索引 / 索引(Staging Area / Staging Index / Index) Git 目录下的一个文件,存储的是即将进入下个 commit 内容的信息。可以将暂存区看做准备工作台,Git 将在此区域获取下个 commit。暂存索引中的文件是准备添加到仓库中的文件。
  • SHA SHA 是每个 commit 的 ID 编号。以下是 commit 的 SHA 示例:e2adf8ae3e2e4ed40add75cc44cf9d0a869afeb6
  • 分支(Branch) 分支是从主开发流程中分支出来的新的开发流程。这种分支开发流程可以在不更改主流程的情况下继续延伸下去。
配置git
# 设置你的 Git 用户名
git config --global user.name "<Your-Full-Name>"

# 设置你的 Git 邮箱
git config --global user.email "<your-email-address>"

# 确保 Git 输出内容带有颜色标记
git config --global color.ui auto

# 对比显示原始状态
git config --global merge.conflictstyle diff3

git config --list
Git 与代码编辑器

最后一个配置步骤是让 Git 能与你的代码编辑器结合使用。以下是三个最热门的代码编辑器。如果你使用的是其他编辑器,则在 Google 中搜索“修改 Git 默认编辑器为 X 编辑器”(将 X 替换为你的代码编辑器的名称)。 Atom Editor 设置

git config --global core.editor "atom --wait"

Sublime Text 设置

git config --global core.editor "'C:/Program Files/Sublime Text 2/sublime_text.exe' -n -w"

VSCode 设置

git config --global core.editor "code --wait"
创建git仓库

在对 Git 仓库进行 commit 或执行任何其他操作之前,需要一个实际存在的仓库。要使用 Git 新建一个仓库,我们将使用 git init命令。 init 子命令是"initialize"(初始化)的简称,这个命令很有用,因为它将进行所有仓库初始设置

  • ls - 用来列出文件和目录
  • mkdir - 用来新建目录
  • cd - 用来更改目录
  • rmz- 用来删除文件和目录

使用 cd 可以更改工作目录,使用 ls(单独使用)会列出工作目录下的文件。如果你忘记 shell 的当前工作目录,可以使用 pwd 命令(表示 print working directory 输出工作目录)输出该目录的名称。

git init 命令的作用

运行 git init 命令会初始化 Git 跟踪所有内容会用到的所有必要文件和目录。所有这些文件都存储在叫做 .git(注意开头有个 .,表示在 Mac/Linux 上,它将是一个隐藏目录)的目录下。这个 .git 目录是一个库!Git 会将所有 commit 记录在这里,并跟踪所有内容

克隆现有仓库

在 Git 上进行克隆的方法是调用我们将在终端上运行的命令 git clone,然后传入要克隆的 Git 仓库的路径(通常是 URL)。

验证终端位置 提示:在克隆任何内容之前,确保命令行工具已定位于正确的目录下。克隆项目会新建一个目录,并将克隆的 Git 仓库放在其中。问题是无法创建嵌套的 Git 仓库。因此,确保终端的当前工作目录没有位于 Git 仓库中。如果当前工作目录没有在 shell 的提示符中显示,输入 pwd 输出工作目录。

判断仓库的状态

git-status

  1. On branch master – 这部分告诉我们 Git 位于 master 分支上。你已在术语表中获取了对分支的介绍,那么这是"master"分支(也就是默认分支)。我们将在第 5 节课深入了解分支。
  2. Your branch is up-to-date with 'origin/master'. – 因为我们使用 git clone 从另一台计算机上复制了此仓库,因此这部分告诉我们项目是否与所复制的仓库保持同步状态。我们不会在其他计算机上处理该项目,因此这一行可以忽略。
  3. nothing to commit, working directory clean– 表示没有任何待定的更改。

可以将这一输出结果看作“休息状态(resting state)”(这并不是官方解释,只是我喜欢这么理解!)。因为没有新的文件、没有对文件作出更改、暂存区没有任何需要 commit 的内容……没有更改或操作,因此我喜欢将其称为休息状态。 该命令将:

  • 告诉我们已在工作目录中被创建但 Git 尚未开始跟踪的新文件
  • Git 正在跟踪的已修改文件
查看仓库的历史记录

git log显示有关现有提交信息 git show显示有关给定提交的信息,需要向其提交ID,也就是SHA

  • 要向下滚动,按下
  • j 或 ↓ 一次向下移动一行
  • d 按照一半的屏幕幅面移动
  • f 按照整个屏幕幅面移动
  • 要 向上滚动,按上
  • k 或 ↑ 一次向上移动一行
  • u 按照一半的屏幕幅面移动
  • b 按照整个屏幕幅面移动
  • 按下 q 可以退出日志(返回普通的命令提示符)

显示内容:

  • SHA - git log 将显示每个 commit 的完整 SHA。每个 SHA 都是唯一的,因此,我不需要查看整个 SHA。只需知道前 6-8 个字符即可。如果我们能只显示 SHA 的前 5 个左右的字符,是不是会节省一些空间?
  • 作者 - git log 输出结果显示了每个 commit 的作者!其他仓库可能有多个人协作,因此情况可能不同,但是对于此仓库,只有一个人提交了所有的 commit,因此所有 commit 的作者是一样的。我们需要查看每个 commit 的作者吗?如果我们想隐藏这一信息呢?
  • 日期 - 默认情况下,git log 将显示每个 commit 的日期。但是我们真的关心 commit 的日期吗?知道日期有时会很重要,但是每次都知道日期并不十分重要,在很多情况下都可以忽略。能否隐藏该信息,以便节省空间?

commit 消息 - 这是 commit 消息最重要的部分…我们通常都希望看到此信息,如何使输出结果更简短呢

git log命令有一个选项,可以用来更改仓库信息的显示方式。该选项为 --oneline:

  • git log --oneline

此命令:

  • 每行显示一个 commit
  • 显示 commit 的 SHA 的前 7 个字符
  • 显示 commit 的消息

git log --stat 简介

此命令会:

  • 显示被修改的文件
  • 显示添加/删除的行数
  • 显示一个摘要,其中包含修改/删除的总文件数和总行数

git log -p git log命令具有一个可用来显示对文件作出实际更改的选项。该选项是 --patch,可以简写为 -p:

  • 添加的行所在的位置以及添加了多少行
  • -15,83 表示旧版本(用 - 表示)从第 15 行开始,显示了 83 行
  • +15,85 表示当前版本(用 + 表示)从第 15 行开始,现在变成了 85 行...这 85 行显示在下方
  • 在 commit 中实际进行的更改
  • 用红色标示并以减号 (-) 开头的行是位于文件-
  • 原始版本中,但是被 commit 删除的行 用绿色标示并以加号 (+) 开头的行是 commit 新加的行
查看特定的commit

显示特定 commit 的详情,而不用关心仓库中的所有其他内容 实际上有两种实现方式!

  • 向 git log 提供你要查看的 commit 的 SHA
  • 使用新的 git show 命令
  1. git log -p fdf5493 通过提供 SHA,git log -p 命令将从这条 commit 开始!无需滚动并逐条查阅!注意,它还会显示在所提供的 SHA 之前提交的所有 commit 信息。
  2. git show 运行上述示例命令将仅显示最近的 commit。通常,将 SHA 作为最后一个参数提供给命令:git show fdf5493 git show 命令将仅显示一个 commit。因此,如果你看不到任何其他 commit,不要惊慌。它只显示一个 commit。git show 命令的输出和 git log -p 命令的完全一样。因此默认情况下,git show 会显示:
  • commit
  • 作者
  • 日期
  • commit 消息
  • 补丁信息

但是,git show 可以与我们了解过的大部分其他选项一起使用:

  • --stat - 显示更改了多少文件,以及添加/删除的行数
  • -p 或 --patch - 显示默认补丁信息,但是如果使用了 --stat,将不显示补丁信息,因此传入 -p 以再次添加该信息
  • -w - 忽略空格变化

向仓库中添加commit

要将所有文件提交到仓库中,首先需要将这些文件从工作目录移到暂存区。我们将使用 git add 命令将这三个文件移到暂存区。

使用 git addindex.html添加到暂存区:

 git add index.html

输出结果中现在出现了全新的区域:"Changes to be committed"区域!这一新的"Changes to be committed"区域显示了位于暂存区的文件!目前只显示了 index.html 文件,因此暂存区只有这个文件。 git rm --cached 与 shell 的rm命令不同。git rm --cached 不会破坏任何属于你的文件,它只是从暂存区删掉了文件。 此外,帮助文本中出现了"unstage"(撤消暂存)字眼。将文件从工作目录移到暂存区叫做"staging"(暂存)。如果已移动文件,则叫做"staged"(已暂存)。从暂存区将文件移回工作目录将"unstage"(撤消暂存)。如果你阅读的文档中提示“stage the following files”,则表明你应该使用 git add 命令。

index.html 文件已暂存。我们再暂存另外两个文件。现在我们可以运行以下命令:

$ git add css/app.css js/app.js

句点 . 句点指代当前目录,可以用来表示所有文件和目录(包括所有嵌套文件和目录!)。

    $ git add css/app.css js/app.js
    # 等同于
    $ git add .
git commit

第一段精确地告诉了我们需要执行的操作 - 我们需要为该 commit 提供一条消息。此外 ,任何以字符 # 开头的行将被忽略。在后面还提示:这将是初始 commit。最后,给出了将提交 commit 的文件列表。

因为这是存储库的第一个 commit,我们将使用 commit 消息 "Initial commit"。文本 "Initial commit" 并不特殊,只是第一个 commit 的常用消息。如果你想使用其他消息,完全可以!

关键在于使每个 commit 都有其侧重点。每个 commit 应该记录一项更改。这种说法可能比较主观(完全没问题),但是每个 commit 应该只对项目的一个方面做出更改。

git commit 小结

此命令:

  • 将打开配置中指定的代码编辑器
  • 请参阅第一节课中的 git 配置流程,了解如何配置编辑器) 在代码编辑器中:
  • 必须提供提交说明
  • 以 # 开头的行是注释,将不会被记录
  • 添加提交说明后保存文件
  • 关闭编辑器以进行提交

然后使用 git log检查你刚刚提交的 commit!

git diff

git diff 命令可以用来查看已被加入但是尚未提交的更改。

.gitignore

如果你想将某个文件保留在项目的目录结构中,但是确保它不会意外地提交到项目中,可以使用名称特殊的文件 .gitignore(注意文件名开头的点,很重要!)。将此文件添加到 new-git-project项目根目录。你只需列出希望 git ignore(忽略,不跟踪)的文件名,git 将忽略这些文件。 note: 可以使用touch .gitigore创建该文件

通配符允许你使用特殊的字符来表示某些格式/字符。在 .gitignore 文件中,你可以使用

  • 空白行作为空格
  • # - 将行标记为注释
      • 与 0 个或多个字符匹配
  • ? - 与 1 个字符匹配
  • [abc] - 与 a、b 或 c 匹配
  • ** - 与嵌套目录匹配 - a/**/z 与以下项匹配
    • a/z
    • a/b/z
    • a/b/c/z

标签、分支、合并

git tag

运行 git tag -a v1.0 将为最近的 commit 添加标签。但是如果你想向仓库中很久之前的 Commit 添加标签呢? 只需提供要添加标签的 commit 的 SHA 即可!

$ git tag -a v1.0 a87984
git branch

git branch 命令用来与 git 的分支进行交互:

  • 列出仓库中的所有分支名称
  • 创建新的分支
  • 删除分支

要创建分支,只需使用 git branch 并提供要创建的分支对应的名称。因此,如果你想创建一个叫做"sidebar"的分支,只需运行以下命令: $ git branch sidebar

git checkout

注意,在进行 commit 时,该 commit 将添加到当前分支上。虽然我们创建了新的 sidebar 分支,但是没有向其添加新的 commit,因为我们尚未切换到该分支。如果我们现在进行 commit 的话,该 commit 将添加到 master 分支,而不是 sidebar 分支。我们已经在演示中看到这一情况,要在分支之间进行切换,我们需要使用 git 的 checkout 命令。

$ git checkout sidebar

请务必了解该命令的工作方式。运行该命令将:

  • 从工作目录中删除 git 跟踪的所有文件和目录 (git 跟踪的文件存储在仓库中,因此什么也不会丢失)
  • 转到仓库,并提取分支指向的 commit 所对应的所有文件和目

日志中的分支 提示符中的分支信息很有用,但是最清晰的查看方式是查看git log的输出结果。就像我们需要使用 --decorate 选项来显示 git 标签一样,我们也需要该选项来显示分支。

$ git log --oneline --decorate

活跃分支 提示符将显示活跃分支。但这是我们对提示符进行的特殊自定义,如果你使用的是不同的计算机,判断活跃分支的最快速方式是查看 git branch命令的输出结果。活跃分支名称旁边会显示一个星号 删除分支 分支用来进行开发或对项目进行修正,不会影响到项目(因为更改是在分支上进行的)。在分支上做出更改后,你可以将该分支组合到 master 分支上(这种“分支组合过程”叫做“合并”(merge),稍后将详细讲解) 合并了分支的更改后,你可能不再需要该分支了。如果你想删除分支,可以使用 -d 选项。下面的命令包含 -d 选项,告诉 git 删掉给出的分支(这里是"sidebar"分支)。 $ git branch -d sidebar 注意,无法删除当前所在的分支。因此要删除 sidebar 分支,你需要切换到 master 分支,或者创建并切换到新的分支。

删除内容让人比较紧张。但是不用担心。如果某个分支上有任何其他分支上都没有包含的 commit(也就是这个 commit 是要被删除的分支独有的),git 不会删除该分支。如果你创建了 sidebar 分支,向其添加了 commit,然后尝试使用 git branch -d sidebar 删除该分支,git 不会让你删除该分支,因为你无法删除当前所在的分支。如果你切换到 master 分支并尝试删除 sidebar 分支,git 也不会让你删除,因为 sidebar 分支上的新 commit 会丢失!要强制删除,你需要使用大写的 D 选项 - git branch -D sidebar。

同时查看所有分支
$ git log --oneline --decorate --graph --all

--graph 选项将条目和行添加到输出的最左侧。显示了实际的分支。--all 选项会显示仓库中的所有分支。

合并

当你在主题分支上做出更改后,如果觉得不想要该分支上的更改,则可以删掉该分支,或者你决定要保留更改,则可以将该分支上的更改与其他分支上的更改合并。

将分支组合到一起称为合并 注意 git 中的两种合并:普通合并和快进合并。

但是如果你在错误的分支上进行了合并,可以使用以下命令撤消合并:

git reset --hard HEAD^
快进合并

在我们的项目中,我们检出了 master 分支,我希望它拥有 footer 分支上的更改。用语言描述的话就是“我想要合并 footer 分支。”。注意表述“合并…”;在进行合并时,另一个分支上的更改将出现在当前检出的分支上。

我再强调下,当我们合并时,我们将其他分支合并到当前(检出的)分支上。我们不是将两个分支合并到一个新的分支上。也不是将当前分支合并到其他分支上。

因为 footer 直接在 master 前面,因此这种合并最简单。将 footer 合并到 master 中将导致快进合并(Fast-forward merge)。快进合并将使当前检出的分支向前移动,直到它指向与另一个分支(这里是 footer)指向的 commit 一样为止。

要合并 footer 分支,运行:

$ git merge footer
进行普通合并

现在我们将进行更常见的合并,其中两个分支完全不一样。你会惊讶地发现,实际合并 sidebar 这样的独特分支,操作是完全一样的!

要合并 sidebar 分支,确保你位于 master 分支上,并运行:

$ git merge sidebar

因为合并的是两个完全不一样的分支,因此将提交 commit。在进行 commit 时,需要提供 commit 消息。因为这是合并 commit,因此已经提供了默认消息。你也可以更改消息,但通常都会直接使用默认的合并 commit 消息。因此当你的代码编辑器打开并包含该消息时,直接关闭编辑器以确认使用该 commit 消息。

合并冲突

合并冲突指示符解释 编辑器具有以下合并冲突指示符:

  • <<<<<<< HEAD 此行下方的所有内容(直到下个指示符)显示了当前分支上的行
  • ||||||| merged common ancestors 此行下方的所有内容(直到下个指示符)显示了原始行的内容
  • ======= 表示原始行内容的结束位置,之后的所有行(直到下个指示符)是被合并的当前分支上的行的内容
  • >>>>>>> heading-update 是要被合并的分支(此例中是 heading-update 分支)上的行结束指示符

解决合并冲突 git 使用合并冲突指示符来告诉你两个不同分支上的哪些行导致了合并冲突,以及原始行是什么。要解决合并冲突,你需要:

  1. 选择保留哪些行
  2. 删掉所有带指示符的行
更改最后一个commit

借助 --amend 选项,你可以更改最近的 commit。

$ git commit --amend
还原commit

当你告诉 git 还原(revert) 具体的 commit 时,git 会执行和 commit 中的更改完全相反的更改。我们详细讲解下。假设 commit A 添加了一个字符,如果 git 还原 commit A,那么 git 将创建一个新的 commit,并删掉该字符。如果删掉了一个字符,那么还原该 commit 将把该内容添加回来! 现在我创建了一个包含一些更改的 commit,我可以使用 git revert 命令还原它

$ git revert <SHA-of-commit-to-revert>

因为最近的 commit 的 SHA 是 db7e87a,要还原该 commit: 我需要运行 git revert db7e87a(随即弹出代码编辑器,以便编辑/确认提供的 commit 消息)

重置commit

初看,重置(reset) 似乎和 还原(revert) 相似,但它们实际上差别很大。还原会创建一个新的 commit,并还原或撤消之前的 commit。但是重置会清除 commit!

git reset 命令用来重置(清除)commit:

可以用来:

  • 将 HEAD 和当前分支指针移到目标 commit
  • 清除 commit
  • 将 commit 的更改移到暂存区
  • 取消暂存 commit 的更改

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青玉伏案

Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

上篇博客聊了《git分支管理之rebase 以及 cherry-pick相关操作》本篇博客我们就以Learning Git中的关卡进行展开。下方列举了Learn...

28860
来自专栏好好学java的技术栈

手把手从零开始带你学git和GitHub

版本: 想想你平时用的软件,在软件升级之后,你用的就是新版本的软件。你应该见过这样的版本号:v2.0 或者 1511(表示发布时为15年11月),如下图:

11720
来自专栏信安之路

教你如何去掉git历史中的敏感信息

本章教大家如何使用 GIT 进行一些关于已提交历史的修改、删除操作。比如碰到下列情况时,如何使用 GIT 实现想要的操作:

17600
来自专栏Java后端技术

谈谈分布式版本管理工具Git

Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的...

14320
来自专栏维C果糖

IntelliJ IDEA 中的版本控制介绍(中)

由于 IntelliJ IDEA 支持的版本控制工具非常的多,但咱们真正能够用到的也就两三个而已,因此在本篇博文中,咱们主要介绍 SVN、Git 和 GitHu...

21160
来自专栏有趣的django

27.git的简单使用

安装 https://git-scm.com/downloads 一直点下一步就可以,安装完后打开方法:‘开始菜单’-->'Git'-->''Git Bash ...

34560
来自专栏埋名

Git 常用命令清单笔记

这里是我的笔记,记录一些git常用和一些记不住的命令,这个笔记原本是基于 颜海镜的文章增加的,后面慢慢增加了许多内容,可以看出的的学习轨迹。分享出来方便自己查看...

12030
来自专栏mwangblog

git 远程分支

11120
来自专栏技术视野

使用tail查看并跟踪文本文件的结尾

tail命令是用于查看文本文件末尾的核心Linux实用程序。您还可以使用跟随模式查看实时添加到文件中的新行。tail类似于,用于查看文件的开头

29340
来自专栏古时的风筝

使用 github 做代码管理,知道这些就够了

只要掌握了下面的常用命令,基本上用使用 github 就没有问题。github 有两种认证方式,一种是通过 ssh 私钥的方式,一种通过 https 的账号名...

36680

扫码关注云+社区

领取腾讯云代金券