git总结(4)改变历史,克隆

来源:互联网 发布:linux安装ftp服务步骤 编辑:程序博客网 时间:2024/05/17 22:20

git总结(4)

改变历史


有了git之后我们在程序的世界就具有了时空穿越的能力,回到过去,改变历史,这个功能的应用场景就不用细说了,我们绝不只一次地想要回到过去改变历史,那么现在就来学习git这台时空机的用法吧

cherry-pick

git cherry-pick 的用法非常简单,拣选操作,用户可以将提交重新排列依次叠加起来。
假设我们有ABCDEF 5个标记
我们可以回到git checkout C(回到C处)
然后git cherry-pick E
git cherry-pick F
现在我们的历史就变成了 没有D提交的平行的历史,之所以说平行,是未来发生了改变,C后面的历次提交所对应的ID和提交时间都会改变,这是一个没有D的平行世界。

rebase

这么一个个拣选,一两个还可以,但如果数量达到上百个怎么办,会不会觉得时光机虽然好用,但累觉不爱了。。。
接下来隆重介绍新的命令rebase 变基
语法吗:下面

编号 rebase用法 1 git rebase –onto newbase <since> <till> 2 git rebase –onto newbase <since> 3 git rebase <since> <till> 4 git rebase <since> 5 git rebase continue 6 git rebase skip 7 git rebase abort 8 git rebase -i

上面的命令看似很多,我们简单分类一下,最下面5,6,7是当变基操作发生意外冲突时可以使用在解决完问题冲突的时候执行5继续,也可以直接执行6跳过该提交,或者执行7中止变基操作。
1,2,3,4仔细看下其实都是1的简单标识法

那么变基操作都经历了哪些过程?
1. 首先执行git checkout till
2. 将since.. till写入一个临时文件中
3. git reset –hard newbase 将分支重置到新分支
4. 将临时文件中的提交依次重新提交到新分支上
5. 如果遇到提交已在分支中包含 则跳过
6. 如果在提交过程中遇到冲突,就可以执行5,6,7选择相应的操作。

最后说下交互式变基,也就是git rebase -i …
交互式变基会将since.. till 的提交依次列出来,用户可以修改相应的操作执行保存,剩下的由git完成。
执行git rebase -i后 ,会弹出这样的文档编辑器

pick b3af728 ignore object files. pick 3488f2c move .gitignore outside also
pick 3488f2c move .gitignore outside also works.
pick 48456ab add hello. h
pick b6f0b0a modify hello. h

pick的意思是应用此提交,用户可以通过删除某行,来删除某提交
也可改成reword 表示,在提交的时候允许用户修改说明
eidt的代表应用该提交,但在提交的时候会暂停提示用户 使用git commit –amend以便对提交进行修补,修补完成后用 git rebase –continue继续。
sqush意思是将该提交与前面的提交压缩为一个
fixup作用和上面的类似但是该提交的说明将被丢弃
用户也可以修改每一行的顺序来改变提交的顺序。

丢弃历史操作

用户可以将某个提交之前的历史全部丢弃(提交的文件还是要保留的)
思路:
1. 先回到某提交例如是A
2. 根据A提交生成一个根提交
3. 执行变基操作将A之后的操作变基到新生成的根提交上面
4. 将提交应用到master上就ok了
具体的操作

git commit-tree A^{tree} ##依据A提交的树生成一个跟提交,然后系统会返回这个根提交的ID如8f7f94ba6a9d94ecc1c223aa4b311670599e1f86
git tag 8f7f newbase ##将这个新生成的提交进行标记
git rebase –onto newbase A F##将A到F的提交一次加到根提交上
git checkout master
git reset –hard HEAD@{1}
历史已经被丢弃了

反转提交

前面的命令都是针对单人版本库,当多人共享一个版本库的时候,你的每一次提交都可能成为别人版本库中的一部分,修改历史的操作只能针对自己的版本库,你无法修改别人的版本库,那么这时候你需要做的是重新做一次提交撤销上次的错误提交,git 也为我们提供了这样一个命令
git revert
例如 git revert HEAD

版本库的克隆

不要把鸡蛋放在同一个篮子里

git 的版本库分为裸版本库和带工作区的版本库
通过git clone []克隆的版本库是带工作区的版本库,他有一个相对于原版本库的对等工作区。
git clone [–bare | –mirror] 克隆的版本库是裸版本库,也就是没有工作区的版本库,裸版本库的命名默认是已.git结尾

通过git clone 的版本库同步可以通过pull 命令来拉取原版本库的最新提交,但不能通过原版本库的push命令来推送提交,因为git clone 命令克隆的版本库是带工作区的版本库,如果原版本库往克隆版本库推送提交会造成克隆版本库的提交和工作区不一致,这样是很奇怪的,所以默认情况下是不允许原版本库向克隆版本库推送提交。

通过git clone –bare | –mirro 克隆的版本库的同步可以通过原版本库push 也可以在克隆版本库执行pull操作,那是因为裸版本库没有工作区,所以不存在裸版本库的版本库和工作区不一致的情况。

除了可以通过clone创建裸版本库之外,还可以通过git init [–bare|–mirror]来创建一个裸版本库,创建的裸版本库的使用方式和之前的操作差不多,也可以执行推送操作,但新初始化的裸版本库由于没有任何提交和分支,和原版本库相对应,所以在第一次推动操作的时候需要指明要推送的分支例如
git push [<path>] [master:master | master]

版本库的管理

有以下几点注意的:
1. 可以通过 git fsck 命令来查看版本库里面没有被引用的文件对象
2. 可以通过git prune来清除未被引用的文件
3. 重置操作引入的对象删除由于还被reflog引用着,所以需要先令对应的reflog过期 可以通过git fsck –no-reflogs 来查询
4. 然后再执行prune
5. 令reflog 过期的命令 git relog expire –expire=now –all
6. 上面的命令一般不常用,常用的清理命令是 git gc
7. git gc 会将.git/refs下的对象打包到.git/packed-refs中,丢弃90天前的reflog,对松散对象进行打包,清除两周以前的未被关联的对象,(对象的打包可以实现增量存取节约资源,提升效率,打包后再次提交,添加对象还是会已松散对象的方式出现在.git/refs下,当版本库中有大量松散对象的时候效率会大大降低,所以要养成定期清理版本库的习惯)
8. 其实在对人协作情况下版本库的管理可以实现自动化,因为版本库的pull merge 等操作的时候会隐式调用git gc –auto

今天就到此结束。

0 0