javanli / blog

blog
0 stars 0 forks source link

git梳理二:特殊问题记录 #22

Open javanli opened 4 years ago

javanli commented 4 years ago

1. merge部分commit:cherry-pick

参考Git中只merge部分commit

git cherry-pick e43a6fd3e9,可以把指定的commit提交到当前分支。常用于把bug fix提交合入发布分支。

update:
对于merge节点,需要- m,参考git cherry-pick -m 例子

2. 拯救push -f:reflog

参考从撤销 rebase 谈谈 git 原理

上面这篇文章讲的是如何撤销rebase,跟撤销push -f原理是一样的,都是切换到之前的合适节点,剩下的就好解决了。

简单而言,git记录了每次head变化时的日志,因此可以通过这个日志找到提交记录被修改前的状态,从而回滚。

不得不感叹git的数据结构设计的灵活性。

另外注意,任何时候都不应该使用push -f,任何已提交到远端的记录都不应该被修改。

3. 清理无效分支:git remote prune origin

远端分支被删除时,git默认并不会同步这个删除操作到本地。git remote prune origin这个命令就是清理掉远端已经删除的分支。

通常情况下,这些无效分支并不会有什么问题,只是堆在那里塞满了分支列表有点不方便而已,但是特殊情况下回引起一些问题。

比如小明拉了个叫xiaoming的临时分支,提交了些代码,发了个mr,回头又删掉了。下次他又拉了个临时分支xiaoming/bugfix,做了同样的操作,此时,他本地和远端都没有xiaoming分支,因此正常。如果这个时候有人更新代码,就会报错:xiaoming已存在,不能创建xiaoming/bugfix

因此,通常需要明确分支命名规范,杜绝这种分支名冲突的情况。如果发生了,就要执行git remote prune origin来修复了。

4. 大文件管理git-lfs

关于git的存储原理可以参考Git Internals - Packfiles

表象上来看,git每个commit都索引了完整的文件,即,每个文件的每次修改,都会生成一份全新的索引。但实际上,git在实际存储的时候,对每个文件的版本变化是进行了delta压缩的,因此实际存储时的空间占用相当于存的是diff。

但是很多二进制文件,你修改了一点东西,它并不是像文本文件一样只变化了一点点的。比如一个jpg图片,你在上面加了个黑点,在jpeg编码后,整个二进制文件发生了较大的变化,delta压缩的效率就很低。不只是图片,大部分二进制文件都有这样的问题。

因此,如果有较大的二进制文件,在仓库中经常变化,git仓库的大小很容易膨胀到恐怖的程度。

Git LFS 是 Github 开发的一个 Git 的扩展,用于实现 Git 对大文件的支持。它把大文件单独存放,git中只记录一个索引,可以大大减轻仓库容量的负担。

参考git-lfs