git 工作原理
Workspace工作区
程序员进行开发改动的地方,是你当前看到的,也是最新的。
平常我们开发就是拷贝远程仓库中的一个分支,基于该分支进行开发。在开发过程中就是对工作区的操作。
Index / Stage 暂存区
.git目录下的index文件, 暂存区会记录git add添加文件的相关信息(文件名、大小、timestamp...),不保存文件实体, 通过id指向每个文件实体。可以使用git status查看暂存区的状态。暂存区标记了你当前工作区中,哪些内容是被git管理的。
当你完成某个需求或功能后需要提交到远程仓库,那么第一步就是通过git add先提交到暂存区,被git管理。
Repository 本地仓库
保存了对象被提交 过的各个版本,比起工作区和暂存区的内容,它要更旧一些。
git commit后同步index的目录树到本地仓库,方便从下一步通过git push同步本地仓库与远程仓库的同步。
远程仓库
远程仓库的内容可能被分布在多个地点的处于协作关系的本地仓库修改,因此它可能与本地仓库同步,也可能不同步,但是它的内容是最旧的。
1.任何对象都是在工作区
中诞生和被修改;
2.任何修改都是从进入index区
才开始被版本控制;
3.只有把修改提交到本地仓库
,该修改才能在仓库中留下痕迹;
4.与协作者分享本地的修改,可以把它们push
到远程仓库来共享。
四个区域之间的关系
branch 分支
分支策略
在实际开发中,应该按照几个基本原则进行分支管理:
(1).master分支
应该是非常稳定的,仅用来发布新版本;
(2).开发都在dev分支
,比如1.0版本发布时,再把dev分支
合并到master
上,在master
分支发布1.0版本;
(3).每个人都在dev
分支上干活,每个人都有自己的特性分支,时不时地往dev
分支上合并就可以了。
merge
操作会生成一个新的节点,之前的提交分开显示
D---E test branch
/
A---B---C---F master branch
在master
执行git merge test
,然后会得到如下结果:
D--------E
/ \
A---B---C---F----G master branch
在我们遇到:
1.自己本地add 并commit 但是还没有 push 到远端时,发现代码有问题,
2.改完代码匆忙提交,上线发现有问题,怎么办?
3.改完代码测试也没有问题,但是上线发现你的修改影响了之前运行正常的代码报错,必须回滚.
处理上面的问题我们分 A.没有push 使用 reset 和B.已经push 使用 revert 两种方式处理方式
1.没有push 时 : 用到 reset (重置)
git reset [ --soft | --mixed | --hard ] [提交版本号]
(a) --soft
(温柔的)保留源码,只回退到commit
信息到某个版本.不涉及index
的回退,如果还需要提交,直接commit
即可.
(b) --mixed
(混合):会保留源码,只是将git commit
和index
信息回退到了某个版本.
为默认方式
git reset --mixed 等价于 git reset
(c) --hard
(牢固地) 源码也会回退到某个版本,commit
和index
都会回退到某个版本.(注意,这种方式是改变本地代码仓库源码)
注意
:当在push代码以后,也使用 git reset --hard <commit...>
回退代码到某个版本之前,这样会有一个问题,你线上的代码没有变,线上commit,index都没有变,当你把本地代码修改完强制提交的时候可能会存在冲突
2.已经push 需要使用 git revert (恢复原状)
git revert [提交版本号]
git revert
用于反转提交,执行revert命令时要求工作树必须是干净的.git revert
用一个新提交来消除一个历史提交所做的任何修改.revert 之后你的本地代码会回滚到指定的历史版本,这时你再 git push 既可以把线上的代码更新.
git reset 与 git revert 区别
区别 git revert
是用一次新的commit
来回滚之前的commit
,git reset
是直接删除指定的commit
看似达到的效果是一样的,其实完全不同.
第一:上面我们说的如果你已经push到线上代码库, reset
删除指定commit
以后,你git push
可能导致一大堆冲突,如果落后于线上的版本提交时需要 使用 git push -f
force强制提交.但是revert
并不会.
第二:reset
是在正常的commit
历史中,删除了指定的commit
,这时 HEAD 是向后移动了,而 revert
是在正常的commit
历史中再commit
一次,只不过是反向提交,他的 HEAD 是一直向前的.
问题
A:push 文件1.txt
B:push 文件1.txt(显然冲突),所以先pull,然后手工合并,假如合并过程中,A又push 文件1.txt了。等B合并完,push 文件1.txt时,又冲突掉了。