git - Git 完全删除一个未合并的根节点
问题描述
我们有两个 repo,Repo1 和 Repo2。看起来“某人”将 Repo2 推送到了 Repo1/origin,现在 Repo1 包含 Repo1 和 Repo2。有两个单独的根节点,没有任何东西被合并(幸运的是)。Repo1 也被来自 Repo2 的一大堆标签/分支污染。
一个特定的祖先(Repo2 的根节点又名“初始提交”)如何完全取消任何提交(及其标签/分支)?或者也许是一种不同/更简单的方式来拼接这两个回购?
请注意,这两个存储库都包含多年的工作(因此手动查看每个提交是不切实际的),但是如果需要,每个使用 Repo1 的人都可以重新克隆。
解决方案
从您的文本描述中,我认为您的意思是您有一个存储库,其中包含两个独立的(不相交的,技术上的)提交子图。例如,这里是这样一个存储库的图表:
C--D
/ \
A--B G--H <-- branch1
\ /
E--F <-- branch2
I--J--K--L <-- master
\
M--N <-- develop
这个特定的图有四个“入口点”,即提交F
和H
以 为根的子图中A
和 提交L
和N
以 为根的子图I
。
虽然这样的存储库从根本上没有任何问题或破坏,但将其拆分为两个独立的存储库相对容易。只需从两个克隆开始,它们看起来都像这样。(您可以git clone --mirror
用来制作保留所有 refs 的镜像克隆。请务必擦除它们origin
的 s,以免它们都指向原始组合存储库。)
在一个这样的克隆中,删除任何外部标签(分支名称、标签名称和其他引用(如果存在任何其他引用))到两个子图中之一中的任何提交:
C--D
/ \
A--B G--H <-- branch1
\ /
E--F <-- branch2
I--J--K--L [abandoned]
\
M--N [abandoned]
确保包含指向故意放弃子图的任何标签或其他名称。普通的图形查看命令,如git log
,不会显示未引用的子图:它似乎已被删除,尽管它仍然存在于物理上。最终,未引用的子图会消失,或者您可以使用git gc
. 从此存储库制作的克隆不会有未引用的子图。
在两个克隆中的另一个中,删除对另一个子图的所有引用:
C--D
/ \
A--B G--H [abandoned]
\ /
E--F [abandoned]
I--J--K--L <-- master
\
M--N <-- develop
和以前一样,未引用的子图最终会消失。
请注意,原始的两个独立子图存储库的任何克隆都可以用于这些拆分克隆git push
中的任何一个。就此而言,任何第三个完全独立的存储库也可用于推送到这两个克隆中的任何一个。任何为独立子图中的提交添加名称的推送都将导致整个独立子图进入推送的接收者。 正如您在评论中推测的那样,我怀疑这种情况最初就是这样出现的。
您可以添加一个 pre-receive 钩子来拒绝添加新根提交的新名称,尽管我知道没有这种形式的方便的 pre-receive 钩子。这很容易做到,但速度很慢:运行git rev-list --all --max-parents=0 --count
以计算现有根,然后git rev-list --all --max-parents=0 --count <hash>
再计算根,如果您接受了来自git push
. 如果计数增加,新的推送会添加一个新的根。
请注意,可以添加不属于不相交子图的新根。例如,考虑“之前和建议之后”的图表:
before:
A--B--C <-- master
after:
A--B--C--F--G <-- master
/
D--E
这种预接收钩子会拒绝这样的推送。这可能是您想要的,但可能不是;小心你的程序。:-)
推荐阅读
- reactjs - 无法使用反应挂钩和受控组件在输入中看到键入的文本
- reactjs - 将一个包的导入批量更改为不同的包
- java - DDD 中的通用存储库:如何使此接口通用?
- python - 如何在 Pyspark 中读取由 Pandas 创建的镶木地板
- php - 致命错误:未捕获的类型错误:mysqli_query()
- python - Python TypeError:reduce_noise() 得到了一个意外的关键字
- python - 如何在 Python for Windows 中打开/编辑文件而不锁定它?
- apache-poi - Excel 使用 Java 将 .xls 转换为 .xlsx
- python - 如何在 python 中使用 dotenv 在本地 .env 文件中设置环境变量?
- oracle - 如何使用 Scala 在 Oracle 语句中对一列的每个值使用自定义函数