Git学习笔记#
[TOC]
根据廖雪峰博客《Git教程》整理。
1 什么是Git#
- 分布式:
相比“集中式”:中央服务器,联网
分布式不需要中央的服务器,每个人都有一套完整的版本库。
功能很强大,简单易用。
2 安装Git#
Mac OS X:可以直接在XCode中安装Git
Windows:https://git-scm.com/download/win 直接下载即可
Linux:直接用命令行安装即可
3 创建版本库#
3.1 什么是版本库#
又名仓库,英文是repository,就是一个文件夹。而这个文件夹里面的所有东西全部被管理起来。
因此,创建一个版本库,只要创建一个文件夹就好了。
另,建议不要在路径里面出现任何中文,否则可能会出现奇奇怪怪的问题。
举例:

如图所示,我在桌面下创建了一个GitLearn的文件夹,并且进入这个文件夹,使用git init
命令完成了初始化。
进入gitLearn文件夹,发现多了一个隐藏的文件夹.git,这就是用来管理的。所以没事不要动哦~

3.2 把文件添加到版本库#
写一个readme.txt

然后告诉Git自己是谁

然后进行add和commit。

git commit -m "注释"
尽量要写清楚注释是干什么的。
如图,告诉我1个文件被改动,增加了2行。
第一步是去添加文件,第二步是一次性把所有更改都提交上去。
小结:
第一步git add <filename>
第二步git commit -m "注释"
4 时光机穿梭#
修改了一下这个文件:

并且使用git status
查看当前状态。

告诉我有个文件被修改了但是还没提交。
我们用git diff
查看是哪里被修改了。

然后进行提交:

4.1 版本回退#
再次改动,追加了一个hohoho。

每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit
。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log
命令查看:

精简:git log --pretty=oneline

每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:

如上图,可以用可视化工具看清楚时间线。
现在我们把他恢复到第二个版本。
在Git中,用HEAD
表示当前版本,也就是最新的提交f74bcd...
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
现在,我们要把当前版本append hohoho
回退到上一个版本add some !
,就可以使用git reset
命令:

打开这个readme.txt
,发现已经变成了第二个版本!

我们再git log
一下:

没有第三个版本了!不过没关系,想要恢复,我们用哪个一长串ID即可。

如图,恢复成功。再看看readme.txt的内容:

背后的原理:有一个head指针,仅仅移动head指针,用head指针表示当前版本。
如果找不到这个ID了怎么办?有一个记录了所有命令的文件:
git reflog

这样又可以找到了。
4.2 工作区和暂存区#
- 工作区:电脑里能看到的目录 比如gitLearn
- 版本库 Repository:
.git
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
(图片来自廖雪峰的Git教程)
现在加一行:

再创建一个LICENSE文件:

现在的状态:

都add,然后这两个文件都在暂存区stage了。最后commit:

此时暂存区的内容提交到了master,stage被清空了。
4.3 管理修改#
Git管理的是修改,而不是文件。

加上一行内容。
提交查看status并再次修改。

直接commit。

查看status:

这里面告诉我我没有成功提交修改。no changes added to commit
这说明,必须add提交到暂存区,再commit把暂存区的内容提交到仓库里面。
使用git diff HEAD -- readme.txt
查看区别。

4.4 撤销修改#
当你修改的内容是错误的,如何恢复?
如果不小心加了一行胡话:

4.4.1 还没add#
手动删除最后一行。
也可以用命令:

git checkout -- readme.txt
git restore readme.txt
4.4.2 add了#

然后git status一下:

1 | git restore --staged .\readme.txt |
用此命令即可。
此时git status
发现暂存区没有被修改,但是本地还是有修改。于是用之前的git restore readme.txt
即可成功复原。
4.4.3 commit了#
使用版本回退。当然,前提是还没有push到远程库,否则就真的惨了。
4.5 删除文件#
创建了一个新的文件stupidBoss.txt
,然后对其进行提交。

现在我发现这个文件不能提交,需要删除。
直接在本地删除:

然后git status
:

现在有两种情况:第一,真的要从版本库里也删掉。第二,删错了,老板就是stupid。
如果也要从版本库删掉,那么先git rm stupidBoss.txt
,然后再git commit
就行了。

如果删错了,可以从版本库里面恢复:
git checkout -- stupidBoss.txt

git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
5 远程仓库#
使用GitHub来玩玩。
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa
和id_rsa.pub
这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:
1 | $ ssh-keygen -t rsa -C "youremail@example.com" |
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub
文件的内容:

然后在GitHub上创建一个SSH key。

5.1 添加远程仓库#
先在GitHub上创建一个仓库。

在本地进行关联:

然后push到远程:

哇!push成功啦!

从现在起,只要本地作了提交,就可以通过命令:
1 | $ git push origin master |
把本地master
分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!
5.2 从远程库克隆#
先创建一个带README.md的远程仓库。

然后克隆到本地。
1 | $ git clone git@github.com:michaelliao/gitskills.git |

下面进入gitskills文件夹:

可以使用https,ssh等协议,但ssh最快。
6 分支管理#
如果自己想要开发别的新功能,但是不影响别人的使用,那么自己先在自己的分支里开发,到最后再合并即可。
6.1 创建与合并分支#
首先,我们创建dev
分支,然后切换到dev
分支:
1 | $ git checkout -b dev |
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:
1 | $ git branch dev |
然后,用git branch
命令查看当前分支:
1 | $ git branch |
git branch
命令会列出所有分支,当前分支前面会标一个*
号。
然后,我们就可以在dev
分支上正常提交,比如对readme.txt
做个修改,加上一行:
1 | Creating a new branch is quick. |
然后提交:
1 | $ git add readme.txt |
现在,dev
分支的工作完成,我们就可以切换回master
分支:
1 | $ git checkout master |
切换回master
分支后,再查看一个readme.txt
文件,刚才添加的内容不见了!因为那个提交是在dev
分支上,而master
分支此刻的提交点并没有变:
现在,我们把dev
分支的工作成果合并到master
分支上:
1 | $ git merge dev |
git merge
命令用于合并指定分支到当前分支。合并后,再查看readme.txt
的内容,就可以看到,和dev
分支的最新提交是完全一样的。
注意到上面的Fast-forward
信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master
指向dev
的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward
,我们后面会讲其他方式的合并。
合并完成后,就可以放心地删除dev
分支了:
1 | $ git branch -d dev |
删除后,查看branch
,就只剩下master
分支了:
1 | $ git branch |
因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master
分支上工作效果是一样的,但过程更安全。
switch#
我们注意到切换分支使用git checkout <branch>
,而前面讲过的撤销修改则是git checkout -- <file>
,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch
更科学。因此,最新版本的Git提供了新的git switch
命令来切换分支:
创建并切换到新的dev
分支,可以使用:
1 | $ git switch -c dev |
直接切换到已有的master
分支,可以使用:
1 | $ git switch master |
使用新的git switch
命令,比git checkout
要更容易理解。
分支操作小结#
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
6.2 解决冲突#


(VSCode可以直接识别出来)

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph
命令可以看到分支合并图。