Git:'永久删除' (分支)没有rebase或filter-branch

时间:2016-05-09 17:52:15

标签: git

动机:我有一个特定的场景,Git似乎很适合,但它仍然不同寻常,需要一些特定的工作。基本上它是一堆文本文件(没有代码),它们至少每10秒左右自动更新一次。这些变化可能相当大,并且至少随着时间的推移,存储库的大小变得相对较大。本地存储库位于嵌入式系统上,没有持续的网络连接,因此自然工作流程是在本地收集提交,在有机会时推送它们,然后删除刚刚推送的内容以释放空间(如有必要)。历史记录可能对暂时保留在设备上很有用,但最重要的是,应该可以将其从设备中删除。 (它永远保存在遥控器上)。根据一些特定于应用程序的因素,可能会稍微扩展一下场景,我们可能会在git中利用其他功能,但我概述的基本结构应该保持不变。

更具体地说,存储库有一个本地副本和一个远程,本地只有(特定分支)推送到远程(从不拉)。提交图很简单,直线'一个接一个地提交没有合并或平行线。只要有机会推送(如上所述),就会创建一个新的分支用于进一步的提交。所以我们经常会有一个新的分支,它基本上只是用来组织提交的时间线。除此之外,我们从不改变分支机构。

因此,旧的分支可以被移除,正如所讨论的,这是我们的目标,特别是当空间成为一个问题时。要永久删除'提交和分支,我们尝试了以下内容:

date=$(date +"%m-%d-%y--%H-%M-%S")

git $opt checkout -b "$date"

git $opt branch -d $to_push

# the first commit will be the single 'initial' commit in the master
# branch, which is permanent and never 'deleted'
git $opt replace --graft \
    $(git $opt log -n 1 --pretty="%H") \
    $(git $opt rev-list --max-parents=0 HEAD)

git $opt reflog expire --expire=now --all
git $opt gc --aggressive --prune=now
git $opt repack -a -d -l

opt变量只是指定工作树和git目录。我们执行的移植(使用随后的gc等)成功地消除了来自天真git log的提交,并且确实释放了一些空间,但它似乎没有释放所占用的空间。仍然被保留在提交中;例如,创建,提交然后删除的大文件在以这种方式删除其提交后仍将继续占用空间。我们在实践中没有获得任何特别大的文件,但我认为这种行为更为通用,因为来自更改的数据' (差异?)仍然存放在存储库中,或类似的东西,这是我们关心消除的。

我设法通过向我建议的一些技巧来贬低剩下的结构,例如从“fetch”中删除分支。配置中的glob并运行git fetch --prune origin;和git update-ref -d refs/remotes/origin/05-07-16--15-48-59例如,但这并没有释放有问题的空间。以下数据描述了当前存储库的状态:

$ git log --all --oneline --graph --decorate
* de345b6 (HEAD -> 05-07-16--15-50-56, replaced) sam. mai  7 15:44:16 EDT 2016
| * 50272b5 sam. mai  7 15:44:16 EDT 2016
|/  
| * 0b96272 sam. mai  7 15:29:48 EDT 2016
|/  
| * b764118 sam. mai  7 15:28:13 EDT 2016
|/  
| * efa0536 sam. mai  7 15:14:45 EDT 2016
|/  
| * 40c8806 sam. mai  7 15:13:57 EDT 2016
|/  
| * 6f7c2f9 sam. mai  7 15:12:26 EDT 2016
|/  
| * fa33771 sam. mai  7 15:11:21 EDT 2016
|/  
| * 8698acd sam. mai  7 15:11:08 EDT 2016
|/  
* b2d9486 (origin/master, master) initial
$ git show-ref
de345b670e24ac68bbbf4aa7efd22598ef3c7251 refs/heads/05-07-16--15-50-56
b2d9486d5d427d1ae4bb88828f334454a2fb6954 refs/heads/master
b2d9486d5d427d1ae4bb88828f334454a2fb6954 refs/remotes/origin/master
0b96272e47cab0b29e2706cae83b8154f8e412ea refs/replace/0afdaca4e6d071fc026d209249a7b0532c11122a
b7641184c898ff08917d363435d5f45e5e9664ed refs/replace/498f8846c6a742f96997b599f5e25f5ad20b568c
6f7c2f9b7700b39b4fd837c34ab7911a08d5438a refs/replace/4df4f9cf8cc01500c800f3f04cbbd655a866c9ba
8698acd667d406fab764389b87518d133de887a6 refs/replace/9a91b7248da808a9fc6e1531c4206a6865273005
40c880617db664cb73390d90e1401a049bc8c303 refs/replace/9edc1e243f4f36034a800c566fdeeac511e077a3
efa0536a40e68d92751193fa0c6dec502d77ce72 refs/replace/d6256dbe48a10461e17ca3cf7e7c40700937d249
fa3377117750fd81c703519038268fec89b65dce refs/replace/db9923391013d8e5d2974f328037f6315af85783
50272b55f66b8d7c55305a3502db8e9f88b2db03 refs/replace/de345b670e24ac68bbbf4aa7efd22598ef3c7251

关于主题中提到的标准,我们不希望执行rebasefilter-branch,因为工作树中的数据是实时的并且经常更新,如上所述。我想我们可以将工作树复制到其他地方然后在那里执行删除,但这会进一步加剧空间限制。即使我们将其复制到其他地方并使用rebase或filter-branch成功删除旧数据,我们也需要将实时存储库中的任何新更改rsync复制到复制的数据库并将复制的更改复制回实时存储库中。 ,所有这些都是关于积极阅读和/或修改存储库内容的进程的原子性,这似乎是不必要的麻烦,但我们对此持开放态度。

我们给出的另一个建议是使用format-patcham来序列化'在以文本文件补丁的形式传输后,提交并重建远程存储库上的结构。然后我们可以在本地创建一个新的存储库来删除旧数据。但这听起来也不必要地复杂,而且基本上看起来像重新做git旨在做的工作。我们对这种可能性持开放态度(或者为此转换到另一个VCS的可能性,或者自定义的东西),但似乎我们非常接近于使用它,并且git似乎非常适合我们的用例。 / p>

我可以提供更多详细信息,我还可以重新创建存储库并尝试不同的步骤和/或在流程的各个步骤中显示命令输出。谢谢你的时间。

修改

在吸血鬼的建议之后,以及他要求提供更多信息:

$ git rev-list --all | xargs -l $git describe --all --always            
replace/de345b670e24ac68bbbf4aa7efd22598ef3c7251
replace/0afdaca4e6d071fc026d209249a7b0532c11122a
replace/498f8846c6a742f96997b599f5e25f5ad20b568c
replace/d6256dbe48a10461e17ca3cf7e7c40700937d249
replace/9edc1e243f4f36034a800c566fdeeac511e077a3
replace/4df4f9cf8cc01500c800f3f04cbbd655a866c9ba
replace/db9923391013d8e5d2974f328037f6315af85783
replace/9a91b7248da808a9fc6e1531c4206a6865273005
heads/05-07-16--15-50-56

1 个答案:

答案 0 :(得分:1)

您的问题是您使用git replace git replace使得git假装一个提交实际上是另一个提交,或者在你的情况下,一个提交的父提交是另一个提交的父提交。
但原始对象仍然存在,它们只是在逻辑上替换为大多数git命令,但除非您使用rebasefilter-branch或类似命令,否则不会进行物理替换。

但如果我没有弄错你,你真正追求的是以下几点:

git reset --soft <initial commit>
git commit -m "recording current state as the only commit after the initial commit"

然后重新包装和清理垃圾的东西

你甚至可以在git别名中填充这两个命令,以便在我记忆中使它们成为Git中的原子操作。

相关问题