- 论坛徽章:
- 2
|
回复 7# peijue
说实话,真要case by case的讲解git怎么用,确实会给人很复杂的感觉。
我是有了一些经验后就看了看git存储的格式,就完全放心的使用git了。
因为,假设我想完成什么功能,却暂时不知道应该用什么命令,甚至git根本就没有提供这种功能,自己写几行脚本就搞定。
先说拆分,需要利用git的暂存区域(staging area/index)。 git commit 只是记录index而非working tree的状态。
假设某个分支的历史是: ... <- A <- B, working tree与B相同。并且想将历史改变为: ... <- A <- C <- D <- B'。
首先用git reset HEAD~ 让index回到A的状态,且working tree保持B的状态。
然后将index改变为C的状态 —— 可以用 git add --patch —— 并提交。
然后将index改变为D的状态,提交;最终将index改变为B'(内容与B相同,只是时间戳不同),提交。
然后是丢弃commit,需要用到cherry-pick的概念。
假设某个分支的历史是: ... <- A <- B <- C <- ...
可以重新构造出一个类似的分支, 首先创建temp分支: git checkout A -b temp。
然后将 A<-B 的变化添加到该分支: git cherry-pick B。此时temp分支: ... <- A <- B'
还可以继续git cherry-pick C,此时temp分支: ... <- A <- B' <- C'。
那么如果想丢弃B引入的变化,只要如上面一样,但略过cherry-pick B就行了。
而连续的cherry-pick,可以用git rebase -i。
比如git rebase -i A,就会提示用户编辑一个文件:
pick B
pick C
pick ...
如果保持不变,git就会创建一个临时分支,然后挨个cherry-pick。
如果想略过B,直接删除那一行然后退出编辑器就行。
合并commit。假设分支历史是: ... <- A <- B <- C <- D ... 打算将BC的变化记录在一个commit中: ... <- A <- BC' <- D' ...
与上面类似,可以新分支上用cherry-pick产生一个类似历史:
git checkout A -b temp
git cherry-pick B
# -----
git cherry-pick -n C # 只将B<-C的变化应用到index,但并不产生一个commit
git commint --amend ... # 修改最近一个提交
# ------
git cherry-pick D
...
对应到rebase -i的文件:
pick B
pick C
pick D
...
如果想达到git cherry-pick -n 之后 git commit --amend 的目的,可以将对应行的pick改为squash,或者s:
pick B
s C
pick D
...
再说说pick/squash之外的另一个edit。回到拆分提交,假设历史是: ... <- A <- B <- C ... 想改变为 ... <- A <- B0 <- B1 <- B' <- C' ...
可以在新分支上连续的cherry-pick,并且pick B后用上面的add --patch拆分为B0,B1,B'。
也可以rebase -i,并且将pick B 改为 edit B, git就会在pick B之后停止, 用户用add --patch 改为 B0 <- B1 <- B' 后 再 git rebase --continue 继续执行那个文件之后的其他cherry-pick操作。
edit仅仅是告知git停下来, 并不只是为了拆分提交。 停下来之后完全可以就地增加一些新的改动, 然后继续pick后面的改动。
总之,git其实只需要学习很少量的命令,以及仓库格式(很清晰的);想要的功能就可以做到,大不了自己动手。
之后只是慢慢熟练其他命令,让这些功能实现起来更方便而已。
而不像其他没有公开仓库格式的工具, 想要什么功能却又查不到对应命令的话真的是无能为力。
git仓库的部分格式可以在git pro(有在线英/中版本)后面章节里找到,好像叫git internal。
丢弃、拆分、合并提交的例子这书里也有。
|
|