【问题标题】:What is the optimal way to only sync certain file extensions and exclude other file extensions between separate git branches?仅同步某些文件扩展名并在单独的 git 分支之间排除其他文件扩展名的最佳方法是什么?
【发布时间】:2021-01-25 19:28:19
【问题描述】:

给定 3 个分支,分别是 master、b1 和 b2。 master 分支只关心 *.txt 文件。它需要忽略其他一切。 分支 b1 只需要 master 包含的内容,例如 *.h、*.c、*.cpp 文件,而忽略其他所有内容。 分支 b2 也只需要包含 master 包含的那些,比如 *.jpg、*.png、*.html、*.css 等,其他的忽略。

简而言之,master 分支包含所有分支共有的信息。示例用例:分支 b1 用于生成分支 b2 使用的输出文件,但两者都包含与 master 共享的一些信息。

那么,在 master、b1 和 b2 之间仅同步那些公共文件并让每个分支仅在其分支中包含某些文件扩展名并忽略它不需要的所有其他内容的最佳方法是什么?

我还研究了拥有单独的 git 存储库或子模块或子树的替代方案,但目录结构或嵌套模式几乎没有什么困难。有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: bash git github git-bash


    【解决方案1】:

    让我从这个开始,因为它可能更有用:

    有没有更好的方法来解决这个问题?

    理论上,你完全可以不用master 分支。有三个分支,其中没有一个包含最终组合结果。在 Git 之外进行组装。如果需要,创建一个“孤立分支”(或使用标签)来记录组装结果,或者将组装结果保存在完全不同的存储库中。但是这些都导致了你提到的那些小困难。

    出了什么问题

    Git 根本无法按照您想要的方式工作:您不能(无论如何有用)“关心”某些文件并让其他“不关心”的文件基于分支进行“关心”切换。那是因为“分支”,在您使用的这个词的意义上,不存在

    现在,这是一个强有力的声明,需要证明。显然,分支确实存在。问题在于branch这个词的含义。它有太多的含义,人们只是在它们之间来回切换,没有意识到他们正在这样做,这给他们带来了麻烦。 (另请参阅What exactly do we mean by "branch"?)所以让我们避免使用 Git 真正使用的术语:提交哈希 ID。

    当你运行时:

    git checkout br2
    

    你告诉 Git 做两件事:

    • 保存名称br2 以备将来使用;
    • 将名称br2 转换为提交哈希ID,并从该提交中提取(包括“关心”)所有文件的快照。李>

    第二步 是现在真正重要的一步:只有在以后运行git commit 进行new 提交时才需要第一步,或者其他一些需要名称的 Git 命令(例如,git branchgit statusgit rebase)。

    除了一个例外——你在一个尚未运行的新克隆中看到git checkout——Git 总是有一些提交检出现在。你的git checkout 告诉 Git:扫掉我们现在拥有的那个,然后给我一些其他的提交作为签出的提交

    假设现在,您已签出br1,即提交b100。稍后,name br1 可能意味着一些 other 提交,但现在它意味着那个。你运行 git checkout br2,它告诉 Git 从提交 b100 切换到提交 b200,因为这就是 name br2 的意思 现在。1

    好的,没什么大不了的,对吧?我们正在从提交 b100 转移到提交 b200。 Commit b100 包含 *.h 文件,省略 *.jpg 文件。所以Git“关心”*.h文件,而我们有b100。这些文件被跟踪,这意味着它们在(单个)索引中。不过,我们正在从 b100 转移到 b200,其中包含 *.jpg 文件并省略 *.h 文件。 Git 必须将*.jpg 文件复制到 其索引并删除 *.h 文件 其索引,这意味着它必须删除*.h 文件也来自您的工作树。

    到目前为止,一切都很顺利:您得到了您想要的。但是现在你想去master 并组装零件。 master 这个名字意味着其他一些提交,可能是 a123

    无论你现在如何到达master,从br1(目前为b100)或br2b200),你都没有所有 *.h *.jpg 文件。你只能得到一套或另一套。这里的根本问题是“关心”的发生是因为文件在 Git 的 index 中。在 .gitignore 文件中列出文件,这是您为防止它们进入 Git 的索引而采取的措施,只有在它们不存在的情况下才有帮助——并且当您切换到提交时 拥有文件,Git 将它们放入 Git 的索引中,无论 .gitignore 文件中有什么内容。当您切换到省略文件的提交时,Git 会从 Git 的索引中删除它们,无论 .gitignore 文件中有什么内容。

    索引的内容反映了您签出的提交。每个提交都有该提交中每个文件的完整快照。该快照最终出现在 Git 的索引中。除非您更改它们——例如使用git add、或git rm,或者通过另一个git checkout 来替换它们,否则这些文件将进入下一个 提交。

    最后,当你使用git merge 组合工作时,Git:

    • 找到一个合并基础提交;
    • 将两个分支提示提交与此合并基础进行比较;和
    • 使用它来确定要在新提交中添加什么。

    与任何提交一样,新提交具有所有文件的快照:git merge 进行合并提交时 Git 索引中的所有文件,这些文件是上述合并过程的结果。合并提交与任何其他提交相同:它们具有快照和元数据。唯一让它们特别的地方——使它们合并提交——是它们的元数据中列出了两个(或更多)父提交哈希 ID。

    这些互锁行为妨碍了:master 实际上确实拥有所有文件,在这种情况下,其他分支名称找到的其他提交也需要拥有所有文件,或者master 没有任何文件,在这种情况下,其他分支可以像这样独占,但您不能将它们合并回 master,因为 Git 将找到的共同提交,将充当合并基础,将导致他们将文件添加文件进入master的新提交——并且现在master 拥有所有文件!如果您在返回分支时删除它们,这次合并将删除这些文件。

    归根结底,Git 完全是关于提交commits 决定了一切!提交快照加元数据。 branch name 所做的只是找到一个特定的提交:某个链上的最后一个。可以从多个分支名称进行提交,并且许多或大多数提交同时在多个分支上。所以 name 与提交中的文件无关:当多个名称找到该提交时,它实际上 不能


    1提交哈希 ID 映射的分支名称​​更改,这是 Git 中分支的增长方式。 Git 是为添加新提交而构建的,因此名称更改的正常方式是,它现在意味着一个更新的提交,它通过提交图引导回到旧的提交——以及更多的提交。另见Think Like (a) Git

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 1970-01-01
      • 2012-10-19
      • 2020-07-20
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      相关资源
      最近更新 更多