Git初级实践教程(图文)
关于Git
Git的由来
Linux 的创始人 Linus Torvalds 在 2005 年开发了 Git 的原型程序。当时,由于在 Linux 内核开发中使用的既有版本管理系统的开发方许可证发生了变更,为了更换新的版本管理系统, Torvalds 开发了Git。
说在前面
- Linux和Mac都预装了Git,Windows上Git的安装也很容易找到教程。在此不做赘述。
- Git属于分布式管理,而之前曾经流行的是集中式管理,如果想要了解两者区别,也可以通过搜索引擎查找到需要的资料。在此亦不做赘述。
使用Git
直接进入正题
基本操作
git init——初始化仓库
$ git init
效果:
如果初始化成功,执行了 git init
命令的目录下就会生成.git
目录。这个 .git
目录里存储着管理当前目录内容所需的仓库数据。
git status——查看仓库的状态
$ git status
新建一个文件并再次查看状态:
可以看到:显示新建文件Untracked
git add——向暂存区中添加文件
$ git add
效果:
git commit——保存仓库的历史记录
记录一行信息:
$ git commit -m "First commit"
记录详细信息:
$ git commit
git log——查看提交日志
commit 栏旁边显示的“ 9f129b……”是指向这个提交的哈希值。 Git 的其他命令中,在指向提交时会用到这个哈希值。Author 栏中显示我们给 Git 设置的用户名和邮箱地址。 Date 栏中显示提交执行的日期和时间。再往下就是该提交的提交信息。
只显示提交信息的第一行:
git log --pretty=short
- 只要在 git log命令后加上目录名,便会只显示该目录下的日志。如果加的是文件名,就会只显示与该文件相关的日志。
- 如果想查看提交所带来的改动,可以加上-p参数,文件的前后差别就会显示在提交信息之后。
git diff——查看更改前后的差别
先输入一些内容:
执行 git diff命令,查看当前工作树与暂存区的差别:
注:“ +”号标出的是新添加的行,被删除的行则用“ -”号标出。
提交之后再次查看:
要查看与最新提交的差别,执行以下命令:
这里的 HEAD 是指向当前分支中最新一次提交的指针。
分支操作
git branch——显示分支一览表
git checkout -b——创建、切换分支
等效于以下两条语句:
注:“ * ”表示当前分支。
这时候如果提交,则是在branch-B
分支下提交,如修改README.md:
再切换回主分支可以看到没有本次提交记录:
git merge——合并分支
为了在历史记录中明确记录下本次分支合并,我们需要创建合并提交。因此,在合并时加上--no-ff
参数。
$ git merge --no-ff branch-B
随后编辑器会启动,用于录入合并提交的信息:
注:退出编辑器:
Esc+连按两次大写Z
git log –graph——以图表形式查看分支
这个命令非常好用,务必记住。
更改提交的操作
Git 的另一特征便是可以灵活操作历史版本。借助分散仓库的优势,可以在不影响其他仓库的前提下对历史版本进行操作。
git reset——回溯历史版本
要让仓库的 HEAD、暂存区、当前工作树回溯到指定状态,需要用到 git rest –hard命令:
注:绿色箭头指明了当前所处位置。
注意此时README.md
文件也跟着回退到该时间点:
注:在branch-B添加并合并的内容没有了。
现在切换到之前创建过的feature-A
并写点内容在README.md
:
提交:
现在我们的目标是如下状态:
首先恢复到master与branch-B合并的状态(回溯之前的状态,图中下往上书第三个master节点)
首先,通过git relog
看一下我们执行过的操作
下往上依次是我们执行过的操作。
只要不进行 Git 的 GC(Garbage Collection,垃圾回收),就可以通过日志随意调取近期的历史状态,就像给时间机器指定一个时间点,在过去未来中自由穿梭一般。即便开发者错误执行了 Git 操作,基本也都可以利用 git reflog命令恢复到原先的状态,所以请务必牢记本部分。
我们恢复到branch-B合并后的master:
但是此时合并会发生问题:
打开编辑器:
======= 以上的部分是当前 HEAD的内容,以下的部分是要合并的 feature-A 分支中的内容。
我们在编辑器中将其改成想要的样子:
如上所示,本次修正让 feature-A 与 branch-B的内容并存于文件之中。但是在实际的软件开发中,往往需要删除其中之一,所以在处理冲突时,务必要仔细分析冲突部分的内容后再行修改。
再次提交:
但是如果此时觉得写解决冲突不妥,还想修改提交说明,怎么办呢?
执行以下命令:
编辑器启动:
我们重新编辑内容,保存并退出,完成修改:
验证以下修改是否成功:
成功!
git rebase -i——压缩历史
在合并特性分支之前,如果发现已提交的内容中有些许拼写错误等,不妨提交一个修改,然后将这个修改包含到前一个提交之中,压缩成一个历史记录。这是个会经常用到的技巧。
再来新建一个特行分支:
修改文本:
这里
git commit -am
相当于git add README.md
+git commit -m "C分支"
,因为改动较小,可以使用这种快捷方式
如果我们发现少写了一句话,现在需要修改第五行内容:
查看修改:
提交:
思考:实际上,我们不希望在历史记录中看到这类提交,因为健全的历史记录并不需要它们。为一个错误留一条历史记录是在没必要!
来操作一下,输入:
git rebase -i HEAD~2
用上述方式执行 git rebase
命令,可以选定当前分支中包含HEAD(最新提交)在内的两个最新历史记录为对象,并在编辑器中打开:
我们将 0da8aa9
的 “添加遗漏” 的历史记录压缩到 f512a47
的 “C分支”里。按照下图所示,将 0da8aa9
左侧的 pick 部分删除,改写为 fixup,然后退出:
再次查看分支:
发现“C分支”对应的hash值被修改,所以操作成功,也就是相当于我们提交了一次没有遗漏的操作,而不是一次有遗漏的操作加一次修改遗漏的操作!
现在合并一下:
推送至远程仓库
现在github上创建一个仓库,为了防止与本地冲突,建议不要初始化README.md
:
git remote add——添加远程仓库
在 GitHub 上创建的仓库路径为“ git@github.com:用户名 /git-tutorial.git”。现在我们用 git remote add命令将它设置成本地仓库的远程仓库:
按照上述格式执行 git remote add命令之后, Git会自动将远程仓库的名称设置为 origin(标识符)。
git push——推送至远程仓库
-u
参数可以在推送的同时,将 origin 仓库的 master分支设置为本地仓库当前分支的upstream(上游)。添加了这个参数,将来运行 git pull命令从远程仓库获取内容时,本地仓库的这个分支就可以直接从 origin 的 master分支获取内容,省去了另外添加参数的麻烦。
执行该操作后,当前本地仓库 master分支的内容将会被推送到GitHub 的远程仓库中:
除了 master 分支之外,远程仓库也可以创建其他分支。举个例子,我们在本地仓库中创建 new-D分支,并将它以同名形式 push 至远程仓库:
可以看到多了一个分支:
从远程仓库获取
git clone——获取远程仓库
首先我们换到其他目录下,将 GitHub 上的仓库 clone 到本地。注意不要与之前操作的仓库在同一目录下:
可以看到,执行操作之后多了一个目录。
执行 git clone命令后我们会默认处于 master分支下,同时系统会自动将 origin设置成该远程仓库的标识符。也就是说,当前本地仓库的 master 分支与 GitHub 端远程仓库(origin)的 master 分支在内容上是完全相同的:
用 git branch -a命令查看当前分支的相关信息。添加 -a
参数可以同时显示本地仓库和远程仓库的分支信息。
我们试着将 new-D 分支获取至本地仓库:
注:
-b
参数的后面是本地仓库中新建分支的名称。为了便于理解,我们仍将其命名为new-D
,让它与远程仓库的对应分支保持同名。新建分支名称后面是获取来源的分支名称。例子中指定了 origin/new-D,就是说以名为origin 的仓库(这里指 GitHub 端的仓库)的 new-D 分支为来源,在本地仓库中创建 new-D 分支。
我们在分支new-D下做一些更改并提交,推送至远程仓库:
可以看到提交的效果:
git pull——获取最新的远程仓库分支
现在我们放下刚刚操作的目录,回到原先的那个目录下。这边的本地仓库中只创建了 new-D 分支,并没有在 new-D
分支中进行任何操作:
然而远程仓库的 new-D分支中已经有了我们刚刚推送的提交。这时我们就可以使用 git pull 命令,将本地的 new-D 分支更新到最新状态。当前分支为 new-D 分支:
可以看到,README.md更新了:
GitHub 端远程仓库中的 new-D分支是最新状态,所以本地仓库中的 new-D 分支就得到了更新。今后只需要像平常一样在本地进行提交再 push 给远程仓库,就可以与其他开发者同时在同一个分支中进行作业,不断给 new-D 增加新功能。如果两人同时修改了同一部分的源代码, push 时就很容易发生冲突。所以多名开发者在同一个分支中进行作业时,为减少冲突情况的发生,建议更频繁地进行 push 和 pull 操作。
深入学习的资料
Pro Git
Pro Git 由就职于 GitHub 公司的 Scott ChaconB 执笔,是一部零基础的 Git 学习资料。基于知识共享的 CC BY-NC-SA 3.0 许可协议,可以免费阅读到包括简体中文在内的各国语言版本。点击阅读
LearnGitBranching
LearnGitBranchingA 是学习 Git 基本操作的网站。注重树形结构的学习方式非常适合初学者使用,点击右下角的地球标志还可切换各种语言进行学习。点击开始学习
tryGit
通过 tryGitB 我们可以在 Web 上一边操作一边学习 Git 的基本功能。该教程只有英文版。点击开始学习
其他
- 参考《GitHub入门与实践》