Udacity Git & Github
Git
-
git init
在当前目录下创建新的空仓库。 -
git clone
$ git clone <path-to-repository-to-clone>
创建一个与现有仓库完全相同的副本。 -
git status
显示仓库的当前状态。 -
git log 显示仓库commit信息
git log --oneline 简略显示信息
git log --stat 显示修改信息摘要
git log -p 显示修改的详细信息 -
git show
仅显示一个commit -
git add
$ git add <file1> <file2> … <fileN>
将文件从工作目录移到暂存区 -
git commit
取出暂存区的文件并保存到仓库中 -
git diff
查看已经执行但是尚未 commit 的更改 -
.gitignore 文件
告诉 git 不应跟踪的文件。该文件应该放在 .git 目录所在的目录 -
git tag
$ git tag -a beta
标记特定的 commit 。当添加新的 commit 时,标签不会移动。 -
git branch 管理 git 中的分支,列出所有分支
git branch footer-fix 5bfe5e7 创建新的"footer-fix"分支
git branch -d footer-fix 删除"footer-fix"分支 -
git checkout 切换分支
git checkout -b richards-branch-for-awesome-changes 创建新分支 -b选项 -
git log --oneline --graph --all
查看所有分支 -
git merge
$ git merge <name-of-branch-to-merge-in>
合并 git 分支 -
合并冲突指示符解释
编辑器具有以下合并冲突指示符:
"<<<<<<< HEAD" 此行下方的所有内容(直到下个指示符)显示了当前分支上的行
"||||||| merged common ancestors" 此行下方的所有内容(直到下个指示符)显示了原始行的内容
"=======" 表示原始行内容的结束位置,之后的所有行(直到下个指示符)是被合并的当前分支上的行的内容
">>>>>>> heading-update" 是要被合并的分支上的行结束指示符 -
git commit --amend 向 commit 中添加忘记的文件
添加忘记包含的文件(或文件更改)。假设你更新了整个网站的导航链接颜色。commit 了该更改,并以为完事了。但是后来发现深藏在页面上的一个特殊导航链接没有新的颜色。你可以执行新的 commit 并更新该链接的颜色,但是这样就会出现两个 commit 执行完全相同的任务(更改链接颜色)。
相反,你可以修改最后一个 commit(更新所有其他链接颜色的 commit)以包含这个忘记的链接。要包含忘记的链接,只需:编辑文件、保存文件、暂存文件、运行 git commit --amend。
你对必要的 CSS 和/或 HTML 文件作出了更改,以便修正被遗忘的链接样式,然后保存所有被修改的文件,并使用 git add 暂存所有被修改的文件(就像要提交新的 commit 那样!),但是你可以运行 git commit --amend 来更新最近的 commit,而不是创建新的 commit。 -
git revert
$ git revert <SHA-of-commit-to-revert>
还原之前创建的 commit,通常会用到祖先引用来指代之前的 commit,将 HEAD 和当前分支指针移到引用的 commit。
--hard 选项清除 commit
--soft 选项将 commit 的更改移至暂存区
--mixed 选项取消暂存已被 commit 的更改 -
commit索引
你已经知道可以使用 SHA、标签、分支和特殊的 HEAD 指针引用 commit。有时候这些并不足够,你可能需要引用相对于另一个 commit 的 commit。例如,有时候你需要告诉 git 调用当前 commit 的前一个 commit,或者是前两个 commit。我们可以使用特殊的“祖先引用”字符来告诉 git 这些相对引用。这些字符为:
^ – 表示父 commit
~ – 表示第一个父 commit
我们可以通过以下方式引用之前的 commit:
父 commit – 以下内容表示当前 commit 的父 commit
HEAD^
HEAD~
HEAD~1
祖父 commit – 以下内容表示当前 commit 的祖父 commit
HEAD^^
HEAD~2
曾祖父 commit – 以下内容表示当前 commit 的曾祖父 commit
HEAD^^^
HEAD~3
^ 和 ~ 的区别主要体现在通过合并而创建的 commit 中。合并 commit 具有两个父级。对于合并 commit,^ 引用用来表示第一个父 commit,而 ^2 表示第二个父 commit。第一个父 commit 是当你运行 git merge 时所处的分支,而第二个父 commit 是被合并的分支。
Github
-
git remote
$ git remote add repo-on-GitHub URL
连接到多个不同的远程仓库。简写名是用于指代远程仓库位置的名称。通常该位置为 URL,但也可能是同一台计算机上的文件路径。
git remote add 添加到新的远程仓库的连接。
git remote -v 查看远程仓库与连接之间的详细信息。 -
git push
$ git push origin master
从本地仓库向远程仓库推送 commit,包括仓库名和分支名 。 -
git pull
$ git pull origin master
在本地仓库拉取远程仓库更改。
在运行 git pull 时,会发生以下活动:
远程分支上的 commit 会被复制到本地仓库
本地跟踪分支(origin/master)移到指向最新的 commit
本地跟踪分支(origin/master)合并到本地分支(master) -
git fetch
$ git fetch origin master
获取远程更改,检索 commit 和移动跟踪分支。它不会将本地分支与跟踪分支合并。 -
git shortlog
按作者对 commit 分组,显示按字母顺序排序的人名列表,以及他们对应的提交说明。
$ git shortlog -s -n
如果我们只想看到每个开发者的 commit 数量,我们可以添加几个选项:用 -s 仅显示 commit 的数量(而不是每个 commit 的消息),以及用 -n 来按数量排序(而不是按作者姓名的字母顺序)。 -
git log --author="Richard Kalehoff" 使用 --author 选项筛选 commit
git log --grep="border radius issue in Safari" 使用 --grep 选项筛选 commit
Github 项目合作
合作规范
- 在开始任何工作之前,确保阅读项目的 CONTRIBUTING.md 文件。
- 接下来,查看项目的 GitHub 问题
- 查看现有的问题,看是否有哪些内容类似于你想贡献的更改
- 如有必要,创建一个新的 Issue
- 与项目维护者交流你想要做出的更改
- 当开始开发后,将所有工作 commit 到特性分支上;
不要在主分支上工作;
确保给特性分支赋予一个清晰、描述性的名称; - 编写 commit 的一般最佳实践;
频繁少量 commit;
使用清晰、具有描述性的提交说明;
必要情况下,更新 README 文件。
申请推送 Pull Request
Pull Request 是让源仓库拉取你的 commit,并融合在其项目中的请求。要创建 Pull Request,你需要完成一些操作:
- 你必须 fork 源仓库
- 将你的 fork 克隆到你的计算机
- 进行一些 commit(最好是在特性分支上!)
- 将 commit 推送回你的 fork
- 创建一个新的 Pull Request,并选择包含你的新 commit 的分支
压制commit
git rebase 命令可以用来做很多事情。
交互式 rebase $ git rebase -i <base>
$ git rebase -i HEAD~3
交互式地将 commit 变基到我们当前所在的 commit 向前三个的 commit
在 commit 的交互式列表中,所有 commit 都以 pick 开头,但你可以使用其他命令(reword、edit、squash、fixup、exec 和 drop)进行变换。
建议在变基之前创建一个备份(backup)分支,这样便能很容易返回到之前的状态。如果你对变基的结果满意,则可以删除 backup 分支!
rebase 命令
- 使用 p 或 pick – 使 commit 保持原样
- 使用 r 或 reword – 保留 commit 的内容,但修改 commit 说明
- 使用 e 或 edit – 保留 commit 的内容,但先不要执行 commit,以便:
添加新内容或文件
删除内容或文件
修改即将 commit 的内容 - 使用 s 或 squash – 将此 commit 的更改结合到之前的 commit 中(列表中位于其上面的 commit )
- 使用 f 或 fixup – 将此 commit 的更改结合到前一个 commit 中,但删除提交说明
- 使用 x 或 exec – 运行 shell 命令
- 使用 d 或 drop – 删除 commit
何时变基
git rebase 命令非常强大。它可以帮助你编辑提交说明、重新排序 commit、合并 commit 等,真的是一款非常强大的工具。现在的问题是"应该何时进行变基?"。
每当你对 commit 进行变基,Git 将为每个 commit 创建一个新的 SHA!这有很大的影响。对于 Git,SHA 为 commit 的标识符,因此不同的标识符代表着不同的 commit,无论内容是否发生了变化。
如果你已推送了你想进行变基的 commit,则不应变基。如果你在与其他开发者协作,那么他们可能已经在使用你推送的 commit。如果你随后使用 git rebase 来进行更改,并强行推送 commit,则其他开发者现在将无法与远程仓库同步。他们需要对自己的 Git 仓库进行一些复杂的手术,使它们的仓库回到工作状态……甚至可能连这一点都做不了;他们可能得抛弃之前的所有工作,使用你新变基过且强制推送的 commit 重新开始。
通用术语
版本控制系统 / 源代码管理器
版本控制系统(简称 VCS)是一个管理源代码不同版本的工具。源代码管理器(简称 SCM)是版本控制系统的另一个名称。
Git 是一个 SCM(因此也是 VCS!)。Git 网站的 URL 是 https://git-scm.com/ (注意它的域名中直接包含“SCM”!)。
提交(Commit)
Git 将数据看做微型文件系统的一组快照。每次 commit(在 Git 中保持项目状态),它都对文件当时的状况拍照,并存储对该快照的引用。你可以将其看做游戏中的保存点,它会保存项目的文件和关于文件的所有信息。
你在 Git 中的所有操作都是帮助你进行 commit,因此 commit 是 Git 中的基本单位。
仓库(Repository / repo)
仓库是一个包含项目内容以及几个文件(在 Mac OS X 上默认地处于隐藏状态)的目录,用来与 Git 进行通信。仓库可以存储在本地,或作为远程副本存储在其他计算机上。仓库是由 commit 构成的。
工作目录 / 工作区(Working Directory)
工作目录是你在计算机的文件系统中看到的文件。当你在代码编辑器中打开项目文件时,你是在工作目录中处理文件。
与这些文件形成对比的是保持在仓库中(在 commit 中!)的文件。
在使用 Git 时,工作目录与命令行工具的 current working directory (当前工作目录)不一样,后者是 shell 当前正在查看的目录。
检出(Checkout)
检出是指将仓库中的内容复制到工作目录下。
暂存区 / 暂存索引 / 索引(Staging Area / Staging Index / Index)
Git 目录下的一个文件,存储的是即将进入下个 commit 内容的信息。可以将暂存区看做准备工作台,Git 将在此区域获取下个 commit。暂存索引中的文件是准备添加到仓库中的文件。
SHA
SHA 是每个 commit 的 ID 编号。以下是 commit 的 SHA 示例:e2adf8ae3e2e4ed40add75cc44cf9d0a869afeb6
。
它是一个长 40 个字符的字符串(由 0–9 和 a–f 组成),并根据 Git 中的文件或目录结构的内容计算得出。SHA 的全称是"Secure Hash Algorithm"(安全哈希算法)。如果你想了解哈希算法,请参阅我们的计算机科学入门课程。
分支(Branch)
分支是从主开发流程中分支出来的新的开发流程。这种分支开发流程可以在不更改主流程的情况下继续延伸下去。
回到之前关于游戏保存点的示例,你可以将分支看做在游戏中设立保存点后,尝试一个有风险的招式。如果有风险的招式不奏效,则回到保存的位置。令分支非常强大的关键之处是你可以在一个分支上设定保存点,然后切换到另一个分支并继续设定保存点。
了解日志内容
如果你不习惯在命令行上使用分页器,那么 less(英) 用起来会比较奇怪。以下是一些实用技巧:
-
要向下滚动,按下
-
j
或↓
一次向下移动一行 -
d
按照一半的屏幕幅面移动 -
f
按照整个屏幕幅面移动 -
要 向上滚动,按下
-
k
或↑
一次向上移动一行 -
u
按照一半的屏幕幅面移动 -
b
按照整个屏幕幅面移动 -
按下
q
可以退出日志(返回普通的命令提示符)
良好的提交说明
我们来思考一个问题:
如何编写良好的提交说明?为何要编写好的提交说明?
问的好!花点时间编写良好的提交说明,再怎么强调这一点都不为过。
何为好的提交说明呢?问的好,很多人发表过关于这一问题的文章,比如: 如何编写 Git Commit Message - 英|译文 、Commit message 和 Change log 编写指南。在编写好的提交说明时,需要注意以下几个事项:
建议
-
消息篇幅简短(少于 60 个字符)
-
解释提交的作用(不是如何更改或为何更改!)
禁忌
-
请勿解释为何做出了这些更改(下文会深入讲解这一点)
-
请勿解释如何进行了更改(这是
git log -p
的目的!) -
请勿使用单词"and"
-
如果你必须使用 "and",则你的提交说明可能进行了太多的更改,将这些更改拆分为独立的 commit
-
例如 "make the background color pink and increase the size of the sidebar"
在编写提交说明时,我喜欢用以下短语造句:"This commit will…"。你可以补充完整该句子并作为提交说明使用。
通配符速成课程
假设你向项目中添加了 50 个图片,但是希望 git 忽略所有这些图片。这样的话,是否需要将每个文件名都列在 .gitignore
文件中呢?当然不用了,要不然太可怕了!相反,你可以采用一个叫做 通配符(英 的概念。
通配符允许你使用特殊的字符来表示某些格式/字符。在 .gitignore
文件中,你可以使用:
- 空白行作为空格
-
#
- 将行标记为注释 -
*
- 与 0 个或多个字符匹配 -
?
- 与 1 个字符匹配 -
[abc]
- 与 a、b 或 c 匹配 -
**
- 与嵌套目录匹配 -a/**/z
与以下项匹配- a/z
- a/b/z
- a/b/c/z
因此如果所有 50 个图片都是 JPEG 图片,并且位于"samples"文件夹中,那么我们可以向 .gitignore
中添加以下行,使 git 忽略所有这 50 个图片。
samples/*.jpg