基础知识
我们知道git一般把区域分为四个部分,通过不同的命令可以完成每一个区域的切换。对于这四种区域,内心一定要清楚的记住。
git add ..=> 把工作区的内容放入暂存区
git commit .. => 把暂存区的内容提交到本地仓库
git push .. => 把本地仓库推送到远程仓库
版本知识
版本知识
一般HEAD
表示当前版本: HEAD^ 表示上一个版本,HEAD^^上上个版本,HEAD~100往上100个版本
。
当前版本记录
$ git log //查看当前的版本记录
$ git log --pretty=oneline // 简化版的查看当前版本记录(省去了时间和本人)
$ git log --pretty=oneline
fea014ebe02b2dde8d88442fd6a2866f0f7b22fc update a
8f06228d024c544796adf6b8796d8b559af4b846 update c.md
77ace164ccc7063270c0268ec15e4f87b01b49a8 create c
3c7280b9cc8144052c2944b1ac9aca10d123de57 create c.md
b14d862114f8214065fdbc97ebc42326889bd607 create b.mc
b66b422aaae32972955216c3ea9d2464dba3473b create a.md
848833db8bbc8f289dfa89610566b20f2a5c5dcd create a.md
e040a733d1c6ffd7eaf26b1f00c0149e3adaf324 测试删除文件
ace6c17bbed2d7bd476d39c1c9b542967f255aa2 提交2.md到本地仓库
a8ae74e2ff0e10fed7dd508eada245b10aba4cd0 提交2.md到本地仓库
历史版本记录
$ git reflog // 查看历史版本
$ git reflog
fea014e HEAD@{0}: commit: update a
8f06228 HEAD@{1}: reset: moving to HEAD^
a6aed5a HEAD@{2}: commit: update a
8f06228 HEAD@{3}: commit: update c.md
77ace16 HEAD@{4}: commit: create c
3c7280b HEAD@{5}: commit: create c.md
b14d862 HEAD@{6}: commit: create b.mc
b66b422 HEAD@{7}: commit: create a.md
848833d HEAD@{8}: commit: create a.md
1. 检查修改
我们在工作中经常需要对比2个文件的区别,方便我们知道修改的地方。
已修改,未暂存
git diff <filename>// 工作区和(暂存区,本地仓库)的比较
假如我们现在有一个文件a.md,它里面的内容是This is a, 已经被提交到本地仓库过或者已经存放在暂存区过,现在我们需要给a.md添加字段update a,但是还没有提交到暂存区。通过git diff a.md
来判定文件的修改内容。
// a.md
This is a
// 添加字段的a.md
Thid is a
update a
$ git diff a.md
diff --git a/a.md b/a.md
index 483b5ef..dff9281 100644
--- a/a.md
+++ b/a.md
@@ -1 +1,2 @@
This is a
+update a
已暂存,未提交
git diff --cached <filename> // 暂存区和本地仓库文件的比较
我们在创建一个b.md,它里面的内容是This is b, 已经被提交过本地仓库一次,现在我们需要给b.md添加字段update b,但是还已经提交到暂存区。通过git diff --cached b.md
来判定文件的修改内容。
// b.md
This is b
// 添加字段的b.md
Thid is b
update b
$ git diff --cached b.md
diff --git a/b.md b/b.md
index 063936b..5eee7b8 100644
--- a/b.md
+++ b/b.md
@@ -1 +1,2 @@
This is b
+update b
已提交,未推送
git diff master origin/master // 本地仓库和远程仓库的比较
我们在创建一个c.md,它里面的内容是This is c, 已经被提交过远程仓库一次,现在我们需要给c.md添加字段update c,但是还已经提交到本地仓库。通过git diff <branch> <origin/branch>
来判定文件的修改内容。
$ git diff master origin/master
diff --git a/c.md b/c.md
index 39b4fb0..5c88cd0 100644
--- a/c.md
+++ b/c.md
@@ -1,2 +1 @@
This is c
-update c
对比2个版本的指定文件
$ git diff <版本号> <版本号> <文件名>
我们刚刚创建了一个d.md提交到本地仓库,然后更新了它的内容,也提交到本地仓库,想对比本次提交和上一次提交d.md的内容差别。
// 1. 查看我们刚刚提交的版本记录
$ git log --pretty=oneline
fbecc1386e8d1d2bdad26ab65d0a0650f14f7206 update d.md
f4001ea7c5cc5809c03f6b6b15dff616cbf4dc4a create d.md
8f06228d024c544796adf6b8796d8b559af4b846 update c.md
// 2. 对比f4001ea和fbecc13的区别
$ git diff f4001ea fbecc13 d.md
diff --git a/d.md b/d.md
new file mode 100644
index 0000000..fd25f48
--- /dev/null
+++ b/d.md
@@ -0,0 +1,2 @@
+This is d
+update d
// 可以很明显的看出,我们添加了2行代码
// 我们再更新下
$ git reflog
5987f16 HEAD@{0}: commit: 第二次更新d.md
fbecc13 HEAD@{1}: commit: update d.md
f4001ea HEAD@{2}: commit: create d.md
// 2. 对比fbecc13和5987f16的区别
$ git diff fbecc13 5987f16 d.md
diff --git a/d.md b/d.md
index fd25f48..b6f7a8f 100644
--- a/d.md
+++ b/d.md
@@ -1,2 +1,3 @@
This is d
update d
+update d2
总结:
git diff <filename>
工作区和(暂存区,本地仓库)的比较
git diff --cached <filename>
暂存区和本地仓库的比较
git diff <branch> <origin/branch>
本地仓库和远程仓库的比较
$ git diff <版本号> <版本号> <文件名>
对比不同版本的文件
2. 撤销修改
人生谁不犯一点错误,但是git给我们修改错误的机会,这样就可以让你的年终奖不至于因为你的疏忽而没有。
已修改,未暂存
git checkout -- <file> // 不要忘记了整个 --
git checkout .
我们已经有一个a.md,它里面的内容是This is a, 我们无意中添加了add 1这样的字段,但是又没有用处,想撤销添加的add 1,并且还没有放入暂存区。
// a.md
This is a
+ add 1 // 想撤销添加的字段
// 1. 没有撤销之前
$ 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.md
no changes added to commit (use "git add" and/or "git commit -a")
// 2. 撤销
$ git checkout -- a.md
//3. 撤销之后
$ git status
On branch master
nothing to commit, working tree clean
已暂存,未提交
git reset HEAD <file> // 把暂存区的内容退回工作区
git checkout -- <file>
我们已经有一个a.md,它里面的内容是This is a, 我们无意中添加了add 2这样的字段,但是又没有用处,想撤销添加的add 1,并且还已经放入暂存区。
// 1. 没有撤销之前
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: a.md
// 2. 撤回到工作区
$ git reset HEAD a.md
Unstaged changes after reset:
M a.md
// 3. 已经回到工作区
$ 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.md
no changes added to commit (use "git add" and/or "git commit -a")
// 4. 撤销工作区
$ git checkout -- a.md
已提交,未推送
$ git reset --hard HEAD^ //回退到本地仓库的上一个版本
我们已经有一个a.md,它里面的内容是This is a, 我们无意中添加了add 3这样的字段,但是又没有用处,想撤销添加的add 1,并且还已经提交到本地仓库了。
// 1. 已经提交
$ git commit -am 'update a'
[master 2f04a8e] update a
1 file changed, 2 insertions(+), 1 deletion(-)
// 2. 撤销已经提交的
$ git reset --hard HEAD^
HEAD is now at fea014e update a
撤销到指定版本
// 1. 通过历史记录,查到你想要倒退到哪一个版本
$ git log
// 2. 通过撤销
$ git reset --hard '版本号'
// 1.
$ git log
commit fea014ebe02b2dde8d88442fd6a2866f0f7b22fc
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 10:11:20 2017 +0800
update a
commit 8f06228d024c544796adf6b8796d8b559af4b846
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:12:27 2017 +0800
update c.md
commit 77ace164ccc7063270c0268ec15e4f87b01b49a8
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:11:42 2017 +0800
create c
commit 3c7280b9cc8144052c2944b1ac9aca10d123de57
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:07:25 2017 +0800
create c.md
//2. 倒退到 create c.md
$ git reset --hard 3c7280b
// 3. 再次查看当前版本记录,就会发现之前的版本都没有了,最新的也是3c7280b的create c.md
commit 3c7280b9cc8144052c2944b1ac9aca10d123de57
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:07:25 2017 +0800
create c.md
commit b14d862114f8214065fdbc97ebc42326889bd607
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 17:51:03 2017 +0800
create b.mc
commit b66b422aaae32972955216c3ea9d2464dba3473b
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 17:43:08 2017 +0800
create a.md
撤销到指定版本后,还想回到之前的某一个版本
我刚刚撤销到c.md后后悔了,应该倒退到它的上2个版本的,现在怎么办呢?通过git log
又查询不到,愁死我了,这个时候救命天子git reflog
登上历史舞台。
// 查看全部历史记录
$ git reflog
3c7280b HEAD@{0}: reset: moving to 3c7280b
fea014e HEAD@{1}: reset: moving to HEAD^
2f04a8e HEAD@{2}: commit: update a
fea014e HEAD@{3}: commit: update a
8f06228 HEAD@{4}: reset: moving to HEAD^
a6aed5a HEAD@{5}: commit: update a
8f06228 HEAD@{6}: commit: update c.md
77ace16 HEAD@{7}: commit: create c
3c7280b HEAD@{8}: commit: create c.md
上面的记录清晰的告诉我们,我们刚刚退回到了3c7280b
,也可以看到它的上2个版本是8f06228
update c.md
// 1. 退回到8f06228版本
$ git reset --hard 8f06228
// 2. 查看当前版本记录
$ git log
commit 8f06228d024c544796adf6b8796d8b559af4b846
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:12:27 2017 +0800
update c.md
commit 77ace164ccc7063270c0268ec15e4f87b01b49a8
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:11:42 2017 +0800
create c
commit 3c7280b9cc8144052c2944b1ac9aca10d123de57
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 18:07:25 2017 +0800
create c.md
commit b14d862114f8214065fdbc97ebc42326889bd607
Author: sunny <sunny@lianj.com>
Date: Wed Dec 20 17:51:03 2017 +0800
create b.mc
3. 合并多条commit
$ git rebase -i <版本号> // $ git rebase -i HEAD~i
// reabse squash rebase fixup
-i
实际上就是 --interactive
的简写,在使用 git rebase -i
时,我们要在后面再添加一个参数,这个参数应该是 最新的一个想保留的 Commit,就是不会合并的commit。
有的时候开发项目的一个小功能,我们没完成一部分都会git commit
,等到工程完成后,就会出现很多commit,这样不方便管理和查看功能,怎么才能合并多个commit呢?
// 1. 查看提交记录
$ git log
commit b921d5f230b4bfb54307371cca8b15afcdd38236
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:15:18 2017 +0800
commit 3
commit 649eb33de6cb5592bbb9a659cf3c44bdc324317f
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:14:55 2017 +0800
commit 2
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
// 2.现在合并commit2 和 commit 3 , 从commit 1 开始
$ git reabse -i HEAD~2 // 进入交互页面
// 3. 从下面可以看出我们可以用到s(squash)
pick 649eb33 commit 2
pick b921d5f commit 3
# Rebase ee0e1b2..b921d5f onto ee0e1b2 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
// 4. 把commit 3 pick改成 s 就相当于把commit 2 放入commit 3中的前面
pick 649eb33 commit 2
s b921d5f commit 3
// 5. 你会进入一个新的commit 界面 :wq退出
// 6. 再次查看log
$ git log
commit b646746055840c1f98de3bbf498d8ef8f26117e3
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:14:55 2017 +0800
commit 2
commit 3
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
可能会遇到的问题
人生都不是一帆风顺的,在你合并的时候可能会遇到一些问题,例如下面的:
我们在把之前的合并退回来
// 1. 看看目前的状态
$ git status
On branch master
nothing to commit, working tree clean
// 2. 用我们之前的回退到上一个版本
$ git reset HEAD^
// 3. 回退完后
$ 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")
// 4. 在处理成开始的样子,有三个提交记录commit 1 commit 2 commit 3
// 5. 再次进入的时候我们把commit 2 的pick改为s
pick 649eb33 commit 2
pick b921d5f commit 3
// 6
s 649eb33 commit 2
pick b921d5f commit 3
//7. 就会出问题了,我们来看看问题的本源
$ git rebase -i ee0e1b
error: cannot 'squash' without a previous commit
You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
Or you can abort the rebase with 'git rebase --abort'.
看提示是without a previous commit
没有一个先前的提交,我们使用s
的时候和合并到先前的提交,而我们进入交互模式-i
的时候,commit 2
之前确实没有可以插入的commit
// commit 2之前没可以插入的commit
# s, squash = use commit, but meld into previous commit
s 649eb33 commit 2
pick b921d5f commit 3
解决
$ git rebase --abort // 取消本次的合并,重新来
测试
我们测试一下我们的猜想正不正确?
// 1. 有四个commit
$ git log
commit 37fcf0211672026db25d43b25bc1ca76f2877615
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:59:23 2017 +0800
commit 4
commit 0efdd45062fabb687633b195f7866fc2b16c2e03
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:37:19 2017 +0800
commit 3
commit deeece14b4444fde6bbcb4584017ac3e13757d6e
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:36:44 2017 +0800
commit 2
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
// 2. 合并commit 1 前面的三个
$ git rebase -i ee0e1b
// 3. 进入交互页面,把commit 3 和 commit 4 改为 s
pick deeece1 commit 2
s 0efdd45 commit 3
s 37fcf02 commit 4
// 4. 修改完成后
$ git log
commit 00b478bfae42ce72e8080aa8bc0127a956a0f800
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:36:44 2017 +0800
commit 2
commit 3
commit 4
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
4. 分支管理
我们在正式的项目中,往往是分为以下几个分支
- master(主分支)
- develop(开发分支)
- test(测试分支)
- uat(预发布分支)
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
修复一个小bug
已经发布到线上的项目,老板突然说,线上这个字写错了,我们需要立马的修改过来,停下手里的开发工作,那应该怎么做呢?
-
从develop切换到master,然后拉去远程代码
git checkout master git pull origin master
-
从master开出一个新的分支bug
git checkout -b bug
-
然后在bug上面修改错误,修改完成后合并到master分支上面
git checkout master git merge bug
-
完成bug后删除开的分支
git branch -d bug
5. 修改commit的内容
修改最新的一条commit
$ git commit --amend
修改其他的commit
// 1. 查看历史
$ git log
commit fc8e6d60941d5408f7b37d6b1e7ce61311cff8dd
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 17:25:31 2017 +0800
commit 5
commit 922a1b9f8e3136da34fef2f2d05ca42e2cf1c730
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:36:44 2017 +0800
commit 2
commit 3
commit 4
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
// 2. 通过rebase回到我们要修改的commit
$ git rebase -i ee0e1b
// 3. 进入交互模式,把对应的commit 的pick改为e
e 922a1b9 commit 2
pick fc8e6d6 commit 5
// 4. 然后进入了对于的基层
$ git commit --amend
[detached HEAD 2d45119] commit 2 修改了的 commit 3
Date: Thu Dec 21 16:36:44 2017 +0800
4 files changed, 3 insertions(+)
create mode 100644 b.js
create mode 100644 c.js
create mode 100644 m.nmd
// 5. 修改完成
$ git rebase --continue
Successfully rebased and updated refs/heads/master.
// 6. c查看历史
$ git log
commit 3fb44dac394983a26e6790e46934c37fe00ac4af
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 17:25:31 2017 +0800
commit 5
commit 2d4511915ad46ff5e8809f14a29e5c47ff5e1e44
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:36:44 2017 +0800
commit 2
修改了的
commit 3
commit 4
commit ee0e1b28c328792096e4dfea599d38374ce6a480
Author: sunny <sunny@lianj.com>
Date: Thu Dec 21 16:00:04 2017 +0800
commit 1
6. git cherry-pick(也很重要)
$ git cherry-pick // 把对应的commit 复制到其他的分支
参考链接(篇幅有限,但是很重要)
Git笔记(三)——[cherry-pick, merge, rebase]
7. git小知识
$ gitk // 可以调用出git的图形操作界面
参考链接
[如何彻底删除 Git 中的提交