Git格式补丁/捆绑包,用于人类可读的Sneakernet“拉/推”

8
我有两个房间,使用git维护一些源代码,“dev”房间是大部分开发的地方,“deploy”房间是我们实际使用软件的地方。不可避免地,在“deploy”房间也会发生一些更改。我希望两个房间在git中共享相同的历史记录。
限制:
1.由于安全原因,这两个房间没有网络连接。
2.只有文本文件(人类可读)可以离开“deploy”房间。
使用“git bundle”将更改移动到“deploy”房间很简单,并跟踪我们移动到“deploy”房间的最后一个提交。由于仅限于文本,从房间中移出更改更加困难。
目标:像“git pull”一样在我的两个未连接的房间之间来回移动提交,即在两个房间中具有相同的SHA1哈希值。
到目前为止:
  • 我尝试使用git format-patch将更改从部署移回开发,但这样做不会记录合并,因此需要为每个连续的更改集生成不同的补丁集以及一些记录如何重现恰好发生在其中的合并提交。有一些讨论关于为合并提交创建差异文件,但这似乎没有捕获实际的祖先关系,只有更改。看起来补丁可能不是提供必要信息的足够丰富的格式。

  • 可以使用一些打包到文本的脚本将包转换为非压缩和人类可读(稍微)的格式,(然后在下载后再次转换)但我没有找到任何证据表明这样的脚本存在。

  • 也许可以编写一个脚本,从某个公共祖先到最新提交遍历历史,然后a)制作补丁或b)重新创建一些常见引用的合并。

备选方案:我可以将从部署室出来的提交压缩成一个原始补丁,并破坏历史记录,但那么从开发->部署的进一步下载将破坏任何现有的工作副本。不理想。

更新: 我相信git fast-export可以做到我需要的,虽然大多数示例是在整个存储库上工作而不是像git bundle那样部分历史记录。我有一个工作的玩具示例,可以将部分历史记录导出到过时的克隆中,但它要求我手动编辑快速导出输出,以便我添加from <sha1>到第一个提交。如果没有这个修改,导入会创建不同的sha1,然后使用Not updating refs/heads/master (new tip <hash> does not contain <master's hash>)进行投诉。 更新2: 我的git fast-export解决方案确实有效,但它存在带宽问题,因为它通过提供全新文件而不是与以前文件的差异来工作。这是不可接受的,因为我实际上必须阅读所有这些额外的行。

你有没有取得任何进展?我和你一样受到完全相同的限制,得出了同样的结论:必须开发其他脚本来支持此功能。 - Ben
我刚刚回答了自己的问题,概述了我们要做什么。 - L. Robison
1个回答

5
我从未找到完美的解决方案,但我们现在所做的似乎是有效的。主要缺点是部署房间内的提交最初具有一个SHA1,然后在与dev房间合并后更改为另一个SHA1。好消息是git很容易将它们识别为相同的提交,并能够通过它们进行merge
有三个检查点我们必须跟踪:
- dev/master中包含dev房间中最新的开发内容。 - deploy/master中包含部署房间中最新的开发内容。 - dev_deploy_common是两个历史记录共享的最后一个提交。
  1. When we move code from dev to deploy (using a bundle), we bring the commits in as part of the dev_deploy_common branch within the deploy room (git pull into dev_deploy_common), and then from deploy/master do a git merge dev_deploy_common and resolve and conflicts then and there.

  2. When we move code from deploy to dev (which must be a text file) we make a few extra steps:

  3. First we rebase deploy/master onto dev_deploy_common so that all of our patches are contiguous. This is generally easy since we've already handled any conflicts during the merges which occurred when bringing the bundle from dev to deploy.

  4. Second we generate a patch set using

    git format-patch -M25 -C25 --find-copies-harder -k --ignore-if-in-upstream
    

    The -M25 -C25 --find-copies-harder options just reduce the output text size. The -k option keeps commit subjects intact. The --ignore-if-in-upstream restricts our commits to just the new ones since dev_deploy_common.

    The result of this is a patchset.txt collection of patches. This file can be hand-reviewed and then moved to the dev room.

  5. In the dev room we import the patchset using the following command:

    git am -k -3 --keep-cr --committer-date-is-author-date patchset.txt
    

    Unfortunately, even though we use all the commands we can to keep the patch exactly the same, a few of the attributes change, primarily the committer. As a result the "same" commit will have different SHA1's in the dev and deploy rooms. This difference will persist until we move a bundle back into the deploy room.

  6. When moving a bundle from dev to deploy, the merge operation (typically) recognizes the identical patches and seamlessly replaces the commit with the one in the dev history. See Step 1.


我很惊讶地发现 git bundle 没有 ASCII 版本,因为在这种情况下,这确实是最好的选择。你尝试关闭压缩以查看捆绑输出吗?无论如何,感谢您提供此功能。 - Walter Nissen
@WalterNissen 我在 git bundle 中没有看到“无压缩”选项。似乎这个格式在这里有描述:https://git-scm.com/docs/pack-format 虽然我没有找到方便的方法来获取未压缩版本。我认为我可以创建一个读取器/写入器来实现这一点,假设“压缩数据”就是其他地方所指明的zlib。 - L. Robison
谢谢你的指引,我可能会尝试解码它们。当我发现如果归档的文件是ASCII格式,那么没有使用-z选项的tar命令会生成ASCII文件时,我从未像那一天那样开心过。 - Walter Nissen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接