1、Git的基本使用
1.1 Git是什么?
Git是目前世界上最先进的分布式版本控制系统(没有之一)
那什么是版本控制系统?如果你用Microsoft Word写过长篇大论,那你一定有这样的经历:
想删除一个段落,又怕将来想恢复找不回来怎么办?有办法,先把当前文件“另存为……”一个新的Word文件,再接着改,改到一定程度,再“另存为……”一个新文件,这样一直改下去,最后你的Word 过了一周,你想找回被删除的文字,但是已经记不清删除前保存在哪个文件里了,只好一个一个文件去找,真麻烦。于是你想,如果有一个软件,不但能自动帮我记录每次文件的改动,这个软件用起来就应该像这个样子,能记录每次文件的改动:
版本 | 文件名 | 用户 | 说明 | 日期 |
---|
1 | service.doc | 张三 | 删除了软件服务条款5 | 7/12 10:38 | 2 | service.doc | 张三 | 增加了License人数限制 | 7/12 18:09 | 3 | service.doc | 李四 | 财务部门调整了合同金额 | 7/13 9:51 | 4 | service.doc | 张三 | 延长了免费升级周期 | 7/14 15:17 |
这样,你就结束了手动管理多个“版本”的史前时代,进入到版本控制的20世纪
1.2 Git的安装
在Windows上使用Git,可以从Git官网直接下载安装程序,(网速慢的同学请移步国内镜像),然后按默认选项安装即可。
安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com
1.3 创建版本库
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
1.3.1 创建一个空目录
$ mkdir learngit
$ cd learngit
1.3.2 初始化仓库
$ git init
Initialized empty Git repository in D:/Git/.git/
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git 的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
1.4 Git常用操作
使用Windows的童鞋要特别注意:千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件!
现在我们在learngit目录下新建一个 a.js 文件,内容如下:
console.log("a");
console.log("b");
1.4.1 git status
git status 命令可以随时掌握仓库的状态
1.4.2 git add
$ git add a.js
1.4.3 git commit
$ git commit -m "wrote a.js"
[master (root-commit) b10aa1b] wrote a.js
1 file changed, 2 insertions(+)
create mode 100644 a.js
简单解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
1.4.4 git diff
我们已经成功地添加并提交了一个a.js文件,于是我们继续修改a.js文件,改成如下内容:
console.log("a");
console.log("b");
console.log("c");
现在,运行git status命令查看结果:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.js
no changes added to commit (use "git add" and/or "git commit -a"
使用git diff 查看版本与库的区别
$ git diff
diff --git a/a.js b/a.js
index 2314941..5cf5101 100644
--- a/a.js
+++ b/a.js
@@ -1,2 +1,3 @@
console.log("a");
-console.log("b");
\ No newline at end of file
+console.log("b");
+console.log("c");
\ No newline at end of file
使用下面的命令将文件提交到仓库中
$ git add readme.txt
$ git commit -m "添加打印c"
$ git status
2. 时空穿梭
2.1 查看历史版本
修改a.js
console.log("a");
console.log("b");
console.log("c");
console.log("d");
然后尝试提交
$ git add a.js
$ git commit -m "添加打印d"
[master 1e7d4ff] 添加打印d
1 file changed, 2 insertions(+), 1 deletion(-)
在Git中,我们用 git log --pretty=oneline 命令查看:
$ git log --pretty=oneline
1e7d4ff9d288e0e4f230f543bd4641df5995b172 (HEAD -> master) 添加
打印d
55559e95b25b3113dba1317398123c80d4e5fa49 添加打印c
b10aa1bcf48e6d21ff8cf0128fd0971e2350864a wrote a.js
2.2 版本回退
用 HEAD 表示当前版本
上一个版本就是 HEAD^
往上100个版本写成 HEAD~100
$ git reset --hard HEAD`
$ git log --pretty=oneline
55559e95b25b3113dba1317398123c80d4e5fa49 (HEAD -> master) 添加
打印c
b10aa1bcf48e6d21ff8cf0128fd0971e2350864a wrote a.js
2.3 版本还原
当我们使用git log命令查看版本库的时候,我们发现最新的那个版本看不到了!如果此时我们想要回到最新版本,该怎么办呢?
Git提供了一个命令git reflog 用来记录你的每一次命令:
$ git reflog
e83249e (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
6975a37 HEAD@{1}: commit: 添加打印d
e83249e (HEAD -> master) HEAD@{2}: commit: '添加打印c'
a97486a HEAD@{3}: commit (initial): wrote a.js
使用下面命令就可以指定回到未来的某个版本:
$ git reset --hard 6975a
HEAD is now at 6975a37 添加打印d
? Git的版本回退速度非常快,因为Git在内部有个指向当前版本的 HEAD 指针,当你回退版本的时候,Git仅仅是把HEAD的指向改变了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M7x0trTY-1665451388017)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/0-1544519271750.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y1Qfz3Uo-1665451388018)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/0-1544519274176.jpg)]
3.工作区和缓存区
? Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
? 先来看名词解释。
3.1 工作区(Working Directory)
? 就是你在电脑里能看到的目录,比如我的 learngit 文件夹就是一个工作区:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zAJa2y9g-1665451388018)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/1581139350602.png)]
3.2 暂存区和本地仓库(Repository)
? 工作区有一个隐藏目录 .git ,这个不算工作区,而是Git的版本库。
? Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master ,以及指向master 的一个指针叫HEAD 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WZ3O6DS-1665451388019)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/0-1544520027136.jpg)]
? 分支和 HEAD 的概念我们以后再讲。
? 前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
>第一步 `git add` 把文件和文件修改添加到暂存区;
>第二步 `git commit` 把暂存区的所有内容提交到当前分支。
? 因为我们创建Git版本库时,Git自动为我们创建了唯一一个master 分支,所以现在git commit 就是往master 分支上提交更改。
3.3工作区、暂存区和本地仓库详解
? 修改a.js,新建b.js
console.log("a");
console.log("b");
console.log("c");
console.log("d");
? 使用git status查看
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
b.js
no changes added to commit (use "git add" and/or "git commit -a")
Git非常清楚地告诉我们,a.js被修改了,b.js是未跟踪状态。
? 使用git add *之后再查看状态
$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: a.js
new file: b.js
? 现在,暂存区的状态就变成这样了:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xi1NT6Xw-1665451388019)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/0-1544520023847.jpg)]
? 所以, git add 命令实际上就是把要提交的所有修改放到暂存区(Stage)。然后执行git commit 就可以一次性把暂存区的所有修改提交到分支。
$ git commit -m '新增b.js,a.js新增打印e'
[master 8261415] 新增b.js,a.js新增打印e
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 b.js
? 一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
$ git status
On branch master
nothing to commit, working tree clean
? 现在版本库变成了这样,暂存区就没有任何内容了:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AkET5qU1-1665451388020)(E:/%E5%AD%A6%E4%B9%A0/01.Git/%E8%AF%BE%E4%BB%B6/assets/0-1544520020528.jpg)]
3.4 撤销修改
3.4.1 撤销工作区的修改
? 继续修改a.js,当我们准备提交代码的时候,发现其中某行代码发生了错误,想要撤回到之前没有修改过的状态。
console.log("a");
console.log("b");
console.log("c");
console.log("d");
console.log("e");
console.log("哈哈");
console.log("嘻嘻");
? 我们使用 git status 命令查看一下:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: a.js
no changes added to commit (use "git add" and/or "git commit -a")
? 你可以发现,Git会告诉你,git checkout -- file 可以丢弃工作区的修改:
$ git checkout -- a.js
? 命令 git checkout -- a.js 意思就是,把a.js 文件在工作区的修改全部撤销,这里有两种情况:
? 一种是 a.js 自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态;
? 一种是 a.js 已经添加到暂存区后同时作了修改,现在撤销修改就回到添加到暂存区后的状态。
? 总之,就是让这个文件回到最近一次 git commit 或git add 时的状态。
? 现在,看看 readme.txt 的文件内容:
console.log("a");
console.log("b");
console.log("c");
console.log("d");
console.log("e");
3.4.2 撤销暂存区的修改
? 假如我们在a.js中做了修改,并且使用 git add 到暂存区了:
console.log("a");
console.log("b");
console.log("c");
console.log("d");
console.log("e");
console.log("哈哈")
console.log("嘻嘻")
$ git add a.js
? 接下来我们使用 git status 查看一下,修改添加到了暂存区,还没有commit:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: a.js
? 接下来Git告诉我们,用命令 git reset HEAD <file> 可以把暂存区的修改撤销掉(unstage),重新放回工作区:
$ git reset HEAD a.js
Unstaged changes after reset:
M a.js
? git reset 命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD 时,表示最新的版本。
? 再用 git status 查看一下,现在暂存区是干净的,工作区有修改:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: a.js
3.5 git reset的三个参数
三者的使用情况:
1.代码编写及修改是在工作区
2.git add 将本地修改添加到暂存区
3.git commit 将暂存区中的内容提交到本地仓库
git reset --hard HEAD^
三者的改变全都丢失,即代码的修改内容丢失
git reset --soft HEAD^
回退到git commit之前,此时处在暂存区。(即执行git add 命令后)
git reset --mixed HEAD^ (默认)
就等于 git reset HEAD 回退到工作区,即git add 之前
3.6 删除
? 要从版本库中删除该文件,那就用命令 git rm 删掉,并且git commit :
$ git rm a.js
rm 'a.js'
$ git commit -m "remove a.js"
[master d46f35e] remove a.js
1 file changed, 1 deletion(-)
delete mode 100644 a.js
? 现在,文件就从版本库中被删除了。
?
? 另一种情况是删错了,没有commit,此时版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git reset
$ git checkout -- a.js
? git checkout 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
git reset HEAD 回退到工作区,即git add 之前
3.6 删除
? 要从版本库中删除该文件,那就用命令 git rm 删掉,并且git commit :
$ git rm a.js
rm 'a.js'
$ git commit -m "remove a.js"
[master d46f35e] remove a.js
1 file changed, 1 deletion(-)
delete mode 100644 a.js
? 现在,文件就从版本库中被删除了。
?
? 另一种情况是删错了,没有commit,此时版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git reset
$ git checkout -- a.js
? git checkout 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
|