基本用法
git add files
把工作目录中的文件加入 stage 缓存
git commit
把 stage 缓存生成一次 commit,并加入 commit 历史 git reset -- files
撤销最后一次git add files
,你也可以用git reset
撤销所有 stage 缓存文件 git checkout -- files
把文件从 stage 缓存复制到工作目录,用来丢弃本地修改
分支
管理分支
git branch
查看当前所有的分支
git branch -v
查看当前所有的分支 + 最后一次提交
git branch --merged
所有已经合并到当前分支的分支(可删除)
git branch --no-merged
所有没有合并到当前分支的分支(不可删除)
git branch -d branch1
删除分支
新建分支
git checkout -b dev
注意,checkout 是根据当前的分支作为基,比如说,你在
branch-10
的分支上git checkout -b branch-11
, 则branch-10
分支修改的代码也会被带到branch-11
。新建一个干净的分支,需要先到
master
分支,再执行git checkout -b dev
合并分支
(dev)$ git add . && git commit -m 'add code'
(dev) git checkout master
(master) git merge dev
解决冲突
冲突的产生:不同的分支改动了同一行代码,并且都提交了
当执行 (master) git merge feature1
时,会遇到冲突,Git 会暂停下来,等待你去解决合并产生的冲突。
出现冲突的文件会包含一些特殊区段,:
<<<<<<< HEAD:index.html
contact : email.support@github.com
=======
please contact us at support@github.com
>>>>>>> iss53:index.html
复制代码
HEAD
表示当前的版本(也就是master 分支),===
用来区分版本。
我们需要人工的去编辑这个文件。
使用git add <filename>
来标记冲突已经解决,之后再git commit -m 'solve conflict'
即可。
分支策略
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
bug 分支
假设,你正在开发iss53
分支,一个大型的项目,提交了一次commit
, 如下图所示。
接到了一个紧急的bug,需要拉取一个bug分支。
-
在拉取之前,需要在
iss53
分支的工作区
和暂存区
变成干净的状态。有两种方法:commit 提交
(适合iss53已经开发完),stash保存进度
(会在下一小结讲到) -
在
iss53
变成干净状态之后,切到master
,拉一个干净的分支hosfix
, -
修复bug,提交一个新的
commit
-
切回到
master
分支,合并hotfix
分支,删除hotfix
分支 -
回到
iss53
的开发中,切回到iss53
分支,如果你需要拉取hotfix
所做的修改,你可以使用git merge master
命令将master
分支合并入iss53
分支,或者你也可以等到iss53
分支完成其使命,再将其合并回master
分支。
git stash
git stash
会把当前工作区
和暂存区
上面的状态,统统存到stash
里面,让当前的工作区
和 暂存区
变成干净的状态
git stash list
可以查看记录
git stash apply stash@{0}
恢复为之前的状态(之前工作区,暂存区的改动会变为工作区的改动)
git stash apply 和分支无关,也就是说,你完全可以
stash
存下来branch1
的改动,然后在branch2
上恢复变更。
回到历史
git checkout
作用: 检出文件、检出提交和检出分支
git checkout [commit-id]
之前的一次commit记录是只读的,绝不会损坏你的仓库。你项目「当前」的状态在 master
上不会变化。
修改历史
git修改历史涉及两个方法:git revert
和 git reset
这两个方法都是基于分支的,因此需要切换到正确分支上。
git revert —— 删除commit
删除 某个之前的commit。如同,那一次commit
就如同当时没有发生过。
但其实,实际上并不是删除那个提交,相反的,会自动产生一个新的提交。在提交中包括了你想要撤销的那个提交的所有反向改动。
git reset —— 回滚到commit
回滚到指定的commit。
在这个版本之后的一个或者多个版本将被真正的放弃,它们也不会显示在分支的历史记录中。
git reset --hard [commitid]
会在回滚之后,让现在工作区中的改动全部丢弃。
git reset --keep [commitid]
会在回滚之后,所有的改动(不管是是在工作区的,还是在暂存区的)都会变成工作区的改动
reset
之后执行git push
操作会报错,因为本地分支落后线上分支,因此需要执行git push -f
如果git reset commit-id 之后后悔了怎么办,比如说我想回到c3, 执行
git reflog
, 就可以找到每一次操作的id了
使用diff
使用diff 可以比较不同版本之间的差异
比较文件 a/b
为了清楚地显示比较信息, diff 操作总是会把要比较的文件定义成 “A” 和 “B”。
文件的元数据 (Metadata)
可以先不用管
标记 a/b
对于版本 A,它的符号是一个减号(“-”);而对于版本 B ,它会使用一个加号(“+”)。
区块(Chunk)
我们只关心有不同的那一段代码,那一段代码被称为区块。
区块标头(Chunk Header)
两个 “@@” 符号中。
来自文件 A (标记为 “-”),从第34行开始之后的6行代码。
来自文件 B (标记为 “+”),从第34行开始之后的8行代码。
使用diff比较不同区
比较工作区,暂存区:git diff
比较暂存区,版本库区: git diff --cached
比较工作区,版本库区: git diff HEAD
比较工作区,和指定commitid: git diff commitid
比较暂存区,和指定commitid: git diff --cached commitid
比较任意两个commitid:git diff commitid commitid
下面使用图片帮助理解: