Step1
首先给大家一个网站
Git中文指南网站
版本管理简介
- 为了管理自己的代码
- 三种流行的版本管理工具Git、Subversion和Mercurlal
- 实际上只有两种,集中式和分散式
Git术语
- Version Control System (VCS) or Source Code Manager (SCM):
A VCS allows you to: revert files back to a previous state, revert the entire project back to a previous state, review changes made over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. - Commit (snapshot):
Git thinks of its data like a set of snapshots of a mini file system. Every time you commit, or save the state of your project in Git, it basically takes a
picture of what all your files look like at that moment and stores a reference to that snapshot.
-Repository (repo):
A directory that contains your project work, as well as a few files (hidden by default in Mac OS X) which are used to communicate with Git. Repositories can exist either locally on your computer or as a remote copy on another computer. - Working Directory:
The files that you see in your computer’s file system. When you open your project files up on a code editor, you’re working with files in the Working Directory. - Checkout:
When content in the repository has been copied to the Working Directory. It is possible to checkout any things from a repository; a file, a commit, a branch, etc. - Staging Area or Staging Index or Index:
A file in the Git directory that stores information about what will go into your next commit. You can think of the staging area as a prep table where Git will take the next commit. Files on the Staging Index are poised to be added to the repository. - SHA:
A SHA is basically an ID number for each commit. It is a 40-character string composed of characters (0–9 and a–f) and calculated based on the contents of a file or directory structure in Git. “SHA” is shorthand for “SHA hash”. A SHA might look like
this:
e2adf8ae3e2e4ed40add75cc44cf9d0a869afeb6 - Branch:
A branch is when a new line of development is created that diverges from the main line of development. This alternative line of development can continue without altering the main line.
Git工作图
上图有三个工作区域,工作目录、暂存区和仓库。
每次更改都要通过暂存区才能上传到仓库中。如果工作目录中的文件在传到暂存区之后再次被修改,再次传到暂存区将会发生合并,并一起提交到仓库中。
Step2
创建自己的仓库
- git init
初始化一个git库 - git clone
从其他地方下载 - git status
当前的状态 git log
显示有关现有提交的信息
git log –oneline
显示简略的commit和SHA的前7个字符
git log –stat
统计了每次提交修改了那些文件
git log -p
圆形 - 正在显示的文件
菱形 - 文件第一版的哈希值和第二版的哈希值
通常不重要,因此可以忽略
❤️ - 文件的旧版本和当前版本
放大镜 - 添加的行所在的位置以及添加了多少行
-15,83 表示旧版本(用 - 表示)从第 15 行开始,文件有 83 行
+15,85 表示当前版本(用 + 表示)从第 15 行开始,现在有 85 行…这 85 行显示在下方
✏️ - 在 commit 中实际进行的更改
用红色标示并以减号 (-) 开头的行是位于文件原始版本中,但是被 commit 删除的行
用绿色标示并以加号 (+) 开头的行是 commit 新加的行
插播一条less的使用方法
git log -p -w
会忽略空格更改
git log -p
就是显示补丁信息,哪些地方被改动了都一目了然
git show
需要给定ID(SHA)来显示该条信息
git show 命令将仅显示一个 commit。因此,如果你看不到任何其他 commit,不要惊慌。它只显示一个 commit。git show 命令的输出和 git log -p 命令的完全一样。因此默认情况下,git show 会显示:commit
作者
日期
commit 消息
补丁信息
Step3
开始提交自己的代码
- git add
在git add不必要的添加到暂存区的时候use “git rm –cached …” to unstage. - gitignore
如果你想将某个文件保留在项目的目录结构中,但是确保它不会意外地提交到项目中,可以使用名称特殊的文件 .gitignore(注意文件名开头的点,很重要!)。将此文件添加到项目中隐藏的 .git 目录。你只需列出希望 git ignore(忽略,不跟踪)的文件名,git 将忽略这些文件。
如果在 .gitignore 文件中输入 *.png,以下哪些文件将被忽略?
trees.png、bg-pattern.png和LOUDFILE.PNG都将被忽略。
git commit
记得要配置自己的编辑器git config --global core.editor <your-editor's-config-went-here>
在代码编辑器中:必须提供提交说明
以 # 开头的行是注释,将不会被记录
添加提交说明后保存文件
关闭编辑器以进行提交
然后使用 git log 检查你刚刚提交的 commit!一个重要的内容是你如何记录你每次提交的修改?
在判断应该在 commit 中包含什么内容时,最好的方法是思考下“如果该 commit 中的所有更改都清空了,会怎样?”。如果删除了某个 commit,应该只撤消一项更改。建议
消息篇幅简短(少于 60 个字符)
解释提交的作用(不是如何更改或为何更改!)
禁忌
请勿解释为何做出了这些更改(下文会深入讲解这一点)
请勿解释如何进行了更改(这是 git log -p 的目的!)
请勿使用单词”and”
如果你必须使用 “and”,则你的提交说明可能进行了太多的更改,将这些更改拆分为独立的 commit
例如 “make the background color pink and increase the size of the sidebar”
在编写提交说明时,我喜欢用以下短语造句:”This commit will…”。你可以补充完整该句子并作为提交说明使用。
最重要的是,在编写提交说明时保持一致性!
- git diff
The git diff 命令可以用来查看已被加入但是尚未提交的更改。
和运行 git log -p 的结果一样!告诉你个秘密,git log -p 其实就是在后台使用了 git diff。所以你实际上已经知道如何阅读 git diff 的输出结果!
- 通配符
通配符允许你使用特殊的字符来表示某些格式/字符。在 .gitignore 文件中,你可以使用:
空白行作为空格
# - 将行标记为注释
* - 与 0 个或多个字符匹配
? - 与 1 个字符匹配
[abc] - 与 a、b 或 c 匹配
** - 与嵌套目录匹配 - a/**/z 与以下项匹配
a/z
a/b/z
a/b/c/z
Step4
分支 branch
git tag
Add tags to specific commits
命令 (git tag -a v1.0) 中,使用了 -a 选项。该选项告诉 git 创建一个带注释的标签。如果你没有提供该选项(即 git tag v1.0),那么它将创建一个轻量级标签。
建议使用带注释的标签,因为它们包含了大量的额外信息,例如:标签创建者
标签创建日期
标签消息- 启用
git log --decorate
选项可以在第一行看到建立的标签。 - 删除标签
如果将标签消息中的某个字打错了,或标签名称打错了(输入 v0.1,而不是 v1.0),如何修正这个错误?最简单的方法是删除这个标签并重新创建。
可以通过输入 -d 选项 (表示 delete 删除!)加上标签名称来删除 git 标签:
git tag -d v1.0
- 向以前的 commit 添加标签
运行 git tag -a v1.0 将为最近的 commit 添加标签。但是如果你想向仓库中很久之前的 Commit 添加标签呢?
只需提供要添加标签的 commit 的 SHA 即可!
git tag -a v1.0 a87984
- git branch
的功能:
- 列出仓库中的所有分支名称(活跃的分支前面有一个*)
- 创建新的分支
git branch abc
创建一个叫做abc的分支 - 删除分支
分支用来进行开发或对项目进行修正,不会影响到项目(因为更改是在分支上进行的)。在分支上做出更改后,你可以将该分支组合到 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 checkout
在不同的branchs之间切换,默认的branch is master。有一个HEAD指针指向master,代表当前master分支是活跃的。假设我有另一个分支叫做sidebar,我想激活sidebar分支我就需要做。
git checkout 命令也可以创建一个新的分支。如果你添加 -b 选项,则能够用一个命令创建分支并切换到该分支。
我们使用新的 git checkout 命令来创建新的 footer 分支并让此 footer 分支的起点位置与 master 分支的一样:
git checkout -b footer master
git checkout sidebar
HEAD指针就指向sidebar就激活了这个分支
- git merge
把不同的分支融合起来。普通合并和快进合并。
当你要合并分支时,务必知道当前位于哪个分支上。注意,合并分支会提交 commit。
- 了解分支
现在我们不知道如何撤消更改。但是如果你在错误的分支上进行了合并,可以使用以下命令撤消合并:
git reset --hard HEAD^
(确保包含 ^ 字符!它属于“相对 commit 引用”并表示“父 级 commit”。我们将在下节课学习相对 commit 引用。)
git merge 指令用来合并 git 分支:
git merge <name-of-branch-to-merge-in>
发生合并时,git 将:
查看将合并的分支
查看分支的历史记录并寻找两个分支的 commit 历史记录中都有的单个 commit
将单个分支上更改的代码行合并到一起
提交一个 commit 来记录合并操作
- 有一个问题合并是谁移动啊?当然是HEAD指向A分支,A分支和B分支合并的时候就是A分支移动。
- 快进合并
在我们的项目中,我们检出了 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 分支)上的行结束指示符
Step5
撤销更改
- git commit –amend
借助 –amend 选项,你可以更改最近的 commit。 git revert
当你告诉 git 还原(revert) 具体的 commit 时,git 会执行和 commit 中的更改完全相反的更改。我们详细讲解下。假设 commit A 添加了一个字符,如果 git 还原 commit A,那么 git 将创建一个新的 commit,并删掉该字符。如果删掉了一个字符,那么还原该 commit 将把该内容添加回来!
git revert <SHA-of-commit-to-revert>
此命令:将撤消目标 commit 所做出的更改
创建一个新的 commit 来记录这一更改git reset
git 根据所使用选项来判断是清除、暂存之前 commit 的更改,还是取消暂存之前 commit 的更改。这些选项包括:–mixed
–soft
–hard
备份分支
注意,使用 git reset 命令将清除当前分支上的 commit。因此,如果你想跟着操作接下来出现的所有重置操作,需要在当前 commit 上创建一个分支,以便用作备份。
在进行任何重置操作之前,我通常会在最近的 commit 上创建一个 backup 分支,因此如果出现错误,我可以返回这些 commit:
git branch backup
- 回到正常状况
如果你在重置任何内容前创建了 backup 分支,那么你可以轻松地让 master 分支指向 backup 分支所指向的同一 commit。你只需:
从工作目录中删除未 commit 的更改 将 backup 合并到 master(这将导致快进合并并使 master 向上移到和 backup 一样的点)
git checkout -- index.html
git merge backup
我们通常会用到祖先引用来指代之前的 commit。祖先引用包含:
^ – 表示父 commit
~ – 表示第一个父 commit