前言
之前总结过git的一些基本命令,后来使用了更多git,写博客用于记录。不断更新 ,在实践中总结git知识点。
回顾下之前的git基本操作
- 将现有的项目添加提交并上传到远程仓库
1 | git add . #添加当前文件夹下的所有文件 |
- clone代码
1 | git clone https://github.com/raymond-zhao/cat-mall.git ../Github/cat-mall |
git status 和 git diff
在对文件进行修改之后,可以用 git status
查看结果,可以让我们时刻掌握仓库当前的状态
可以看到在modified
部分,可以看到有四个文件被修改了,但是还没有进行提交(commit
)修改
而下半部分的untracked files
表示的是之前从未提交到仓库分支的文件(一个markd文件,一个照片)
上述只是看到被修改的文件,但如果能看看具体修改了什么内容就好了,git diff
可以实现这个功能
可以看到修改的详细细节(红色为修改前的内容,绿色为修改后的内容)。向下箭头可以下拉文本,q
退出查看 (quit)
这样就可以放心的添加(add)到仓库的暂存区,并提交(commit)到仓库分支
1 | git add . |
小结
- 要随时掌握工作区的状态,使用
git status
命令。 - 如果
git status
告诉你有文件被修改过,用git diff
可以查看修改内容。
版本回退
每当文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit
。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
在Git中,我们用git log
命令查看:
git log
命令显示从最近到最远的提交日志,每一次commit
很详细
可以加上--pretty=oneline
参数,来简化显示。推荐使用
其中前面编号类似012214236e...
的是commit id
(版本号),是一个SHA1
计算出来的一个非常大的数字,用十六进制表示
每个人的编号不一样,因为Git是分布式的版本控制系统,多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
回退到历史版本
这样我们就可以进行回退操作
首先,Git必须知道当前版本是哪个版本。
在Git中,用HEAD
表示当前版本,也就是最新的提交012214236e...
,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
我们可以使用git reset
命令:
1 | git reset --hard HEAD^ #回退到上一版本 |
结果显示出现在是ca41b0a
,也就是上一次commit
的版本。我们成功回退版本!
当我们再查看日志的时候,发现已经没有20/8/31/commit1
版本了
还原到最新版本
如果想要再还原到20/8/31/commit1
版本呢?
也是可以的,只要上面的命令行窗口还没有被关掉
,就可以顺着往上找,找到那个20/8/31/commit1
版本的commit id
是012214236e...
,于是就可以指定回到未来的某个版本:
1 | git reset --hard 0221423 |
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
这样就实现了还原到最后commit
版本
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD从指向历史版本,再将工作区的文件更新即可
如果回退到了某个版本,关掉了命令行窗口,后悔想恢复到新版本但是找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。Git提供了一个命令git reflog
用来记录你的每一次命令:
知道commit_id
,还原版本就十分滴完美!
注!!!
如果从历史版本回到最后的版本,也只能还原到最后
commit
后的版本。我才开始
commit
了版本A,之后又写了一部分内容 B(未commit
)。还原到了A-1版本,之后又想还原到A+B版本,操作完之后发现还原后的没有B部分,也就是我只能还原到A。原因就是我在最后一次
commit
就是A,而写完B之后,没有commit
,于是无法还原。 (多多commit
,,还原需谨慎。我是真的折腾)😭
小结
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。 (commit_id也写成HEAD^)- 穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
参考
工作区和暂存区
工作区(Working Directory)
就是在电脑里能看到的目录,比如我的mynlog
文件夹就是一个工作区:
版本库(Repository)
也就是本地仓库
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。(选择隐藏文件可见
就可以看到)
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index
)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区(index
);
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支(master
)。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。 也就是可以多次git add .
,之后再一次性git commit
我对文件进行修改之后,git status
显示如下:
这是对文件进行了修改,但是未添加(add)到暂存区和提交(commit)到仓库分支。 并且出现了之前从未提交的文件(四张png图片)
然后git add .
,再查看目前的状态 git status
出现了绿色的new file
字样和modified
,代表已添加到缓存区。
现在,暂存区的状态就变成这样了(原文是添加的readme和LICENSE文件):
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(index),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
这时候再 git status
,则是干净的
现在版本库变成了这样,暂存区就没有任何内容了:
小结
了解工作区和暂存区的概念,并通过例子加强git status
、git add
、git commit
的理解
如果不用git add
到暂存区,那就不会加入到commit
中。也就是说commit
只会提交暂存区里的内容
撤销修改
在工作区撤销修改
在工作区写的内容想要撤销,当然可以手动删除。同时还有另外的一种方法
git status
查看一下状态
根据git提示,可以知道如下信息:
changes not staged for commit
:表示没有更改添加到暂存区,也就是对于当前的修改还没有进行add
操作
可以看到修改的部分是
2020-08-31-git 进阶.md
文件,不能显示中文,所以用编码表示同时
next
文件也做了修改。这个每次都有提示,猜想应该是因为next是我clone
下来的文件,所以存在.git
文件,将.git
文件删除就ok了提示显示,
git checkout -- file
可以丢弃工作区(work directory)的修改
git checkout -- file
1 | git checkout -- source/_posts/2020-08-31-git进阶.md (注意--不要遗漏,同时后面有一个空格) |
命令git checkout -- filename
意思就是,把filename
文件在工作区的修改全部撤销,这里有两种情况:
- 一种是文件自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- 一种是文件已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit
或git add
时的状态。
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
注
- 文件必须写当前git bash 下的完整路径,可以参考
git status
下的modified部分路径名称,如上的source/_posts/
- 文件名必须写中文(就是正常的文件名),不能按照modified部分的编码后的名称
这是错误过程,可以看到最后一次没有提示,表示成功撤销修改
打开git进阶文件可以看到内容已经撤销
添加到暂存区后的撤销
如果在工作区已经修改,并且添加到暂存区了,在commit
之前,发现了这个问题。用git status
查看一下,修改只是添加到了暂存区,还没有提交:
- 在添加到暂存区后,可以看到在
changes to be committed
部分,添加的部分已经变成绿色,等待被commit
提交 - 根据git提示,用命令
git reset HEAD <file>
可以把暂存区的修改撤销掉(unstage
),重新放回工作区:
1 | git reset HEAD . |
git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD
时,表示最新的版本。
撤销到工作区的内容可以根据上述内容撤销其修改
提交到版本库后的撤销
前提是还没有把自己的本地版本库推送到远程。
可以利用上述的版本回退
功能
小结
- 场景1:当你改乱了
工作区
某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
。 - 场景2:当你不但改乱了工作区某个文件的内容,还
添加到了暂存区
时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按场景1操作,用命令git checkout -- file
。 - 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考
版本回退
,不过前提是没有推送到远程库。
远程仓库
已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作。
首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库
在Repository name填入shijian
,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库。出现以下界面:
复制仓库的SSH链接
根据提示,可以返回到需要上传的文件夹目录下,右键选择git bash
1 | git init #创建.git隐藏文件,用于本地仓库 |
添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。
接下来就是git的基本三样操作,添加提交并推送
1 | git add . #添加当前文件夹下的所有文件 |
把本地库的内容推送到远程,用git push
命令,实际上是把当前分支master
推送到远程。这时候在github界面就可以看到推送的文件
第一次push的时候可以添加参数
-u
,之后可以不添加由于远程库是空的,我们第一次推送
master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
分支
分支暂时用不到,就没有学习