什么是版本控制
所谓的版本控制就是在文件修改的过程中保存了修改历史,有了这些修改历史可以很方便的撤销以前对文件的操作。
在git中的每一次提交就是一个版本,git将这些版本信息保存在git仓库中,开发者可以从git仓库中找到这些历史版本,从这些历史版本中可以查看对应的修改内容、撤销或者修改之前的操作。
集中式版本控制 VS 分布式版本控制
git属于分布式版本控制系统。分布式和集中式的区别在于,分布式除了中央仓库之外还有本地仓库,每个开发者的机器上都有一个本地仓库,这个本地仓库包含了所有的版本历史,git中的很多操作都是和本地仓库交互,所以不需要联网也可以继续工作。只有在从远程仓库拉取和提交代码时才需要联网操作。
而集中式版本控制系统的特点是只有一台中央服务器,存放着所有版本历史。而其它客户端机器上保存的是中央服务器最新版本的文件快照,不包括项目文件的变更历史,每次提交都需要联网操作。
所以中央仓库在这两个系统中的作用:
分布式:同步代码
集中式:同步代码、保存版本历史
Git中的HEAD、branch
HEAD:始终指向当前commit
git log第一行commit后面括号中的内容都是指向当前commit的引用,这里可以看出HEAD是指向master(分支)然后间接指向当前commit,用一张图表示:
通常情况下我们可以理解为HEAD指向当前所在分支,然后间接指向最新的一次commit。
但是当HEAD处于detached状态时,它就直接指向commit而不指向任何分支。
git checkout --detach上图可以看到此时HEAD直接指向commit。过程如下图:
HEAD 是 Git 中一个独特的引用,它是唯一的。而除了 HEAD 之外,Git 还有一种引用,叫做 branch(分支)。HEAD 除了可以指向 commit,还可以指向一个 branch,当它指向某个 branch 的时候,会通过这个 branch 来间接地指向某个 commit;另外,当 HEAD 在提交时自动向前移动的时候,它会带着它所指向的 branch 一起移动。
如果在这里提交一次commit,HEAD会带着branch向前移动
git commit先在可以在log中查看
git log可以看出在创建新的commit后,HEAD和master都指向了它
分支管理
分支是Git很强大的特性。日常开发中我们都不会在master分支进行,而是在新建分支上开发,开发完成后再进行合并。在此过程中经常会遇到各种问题,我也记录下自己在工作过程中在分支管理方面出过错的地方:分支合并、版本回退
1.版本回退
一般版本回退的方式有两种:reset和revert。
他们的区别在于,reset 是将一个分支的末端指向另一个提交(移动HEAD以及它指向的branch),这可以用来移除当前分支的一些提交。revert在撤销的同时会创建一个新的提交。
git reset图示:
reset前
现在执行reset回到2c9728101101d的版本
git reset 2c9728101101d --hard从log中可以看到reset后最新的一次commit就是2c9728101101d,reset之前的两次commit被移除。如果之前已经将代码提交到远程,reset后再次推送的话会提示版本落后,此时需要强制提交。
git reset参数:
--hard 重置位置的同时,清空工作目录的所有改动
--soft 重置位置的同时,保留工作目录和暂存区的内容
--mixed 重置位置的同时,保留工作目录的内容,并清空暂存区(默认)再次执行revert,撤销2c97281011这次提交
git revert 2c9728101101d3efa8e可以看到这里新增了的一条commit 58d2eb2a85087
2.分支合并
merge 时的目标 commit 和 HEAD 处的 commit 并不存在分叉,当前分支领先目标commit:空操作merge 时的目标 commit 和 HEAD 处的 commit 并不存在分叉,当前分支落后目标commit:fast-forwardgit rebase:给commit序列重新设置基础点(也就是父commit),也就是说把指定的commit以及它所在的commit串,以指定的目标commit为基础,依次重新提交一次。git checkout branch1
git rebase masterrebase,5和6两条commits把基础点从2换成了4。通过这种方式,就让分叉的提交记录重新回到了一条线。而且rebase 后的 commit 虽然内容和 rebase 之前相同,但它们已经是不同的 commits。rebase后要切回到master再merge一下,把master移动到最新的commit。