Git:如何强制将文件推送到所有分支

时间:2018-06-28 10:33:03

标签: git android-studio

我有一个示例android项目存储库,我在其中为Android中的每个主题创建示例,并保留在不同的Git分支中,以便随时可以切换到相应的分支并获取特定主题的示例代码。

基本上,我在Git中只有一个Android项目,但是每个分支都有不同的代码库。目前我在那有20多个分支。

但是有些配置文件(例如build.gradle)保留了库版本,sdk版本等。这些文件无论任何分支,我都需要更新。

因此,每当我对此配置文件进行更改时,我都希望将其推送到所有分支,从而覆盖旧的配置文件。

说,如果要进行库更新,则在master分支中更新版本并推送。但这仅影响客栈的master分支。

所有其余19个分支将具有旧版本代码。我将不得不切换到每个分支,并从master合并此配置文件。

是否有单个命令可以执行此操作?这样我可以在一个分支中更新文件,然后可以强制将其推到所有其他分支?

1 个答案:

答案 0 :(得分:2)

  

是否有单个命令可以执行此操作?这样我可以在一个分支中更新文件,然后可以强制将其推到所有其他分支?

不。从概念上讲,Git的工作方式没有任何意义:git push不会推送文件git push按下 commits

提交是每个文件的完整快照。也就是说,给定一些提交哈希ID(哈希ID是提交的实际名称),您可以让Git枚举每个文件及其内容,并以其当时在索引/登台区域中采用的任何形式永久地永久冻结您(或任何人)运行了git commit。更有用的是,给定相同的哈希ID,您可以git checkout <hash-ID>并用这些文件填充工作树(以及索引/临时区域!)。

因此,如果快照中存在build.gradle(即提交),则提取该提交将以该快照中具有的形式为您获取build.gradle文件。到目前为止,这都应该非常简单,而且大部分都是您想要的。现在,让我们看看进行新提交的含义。

我们已经注意到,每个提交都有一个哈希ID。这些ID似乎是随机的,尽管实际上它们实际上是提交的完整内容的加密哈希。它们太难让人直接使用。因此,Git提供了一种以人类可读的名称(例如{{1})存储某个分支的 latest 哈希ID(Git称为分支的 tip )的方法。 }。

这些名称存储一个(1)哈希ID。因此,如果您只知道最新的提交,那么您或Git如何找到任何更早的提交?答案是,每个Git提交都将其自身存储为一部分-由于它是提交内容的一部分,因此将进入其自身哈希ID的计算中-该分支的 previous 提示的哈希ID 。也就是说,给定一些提交顺序:

master

(使用大写字母表示实际的哈希ID),您可以通过让Git进行... <-E <-F <-G <--master parent H的提交来添加新的提交。哈希。然后,Git将新的哈希写入名称G中,以使master指向master

H

由于... <-E <-F <-G <-H <--master 推送了 commits (不是文件),因此您将需要提取每个分支提示,包括其所有文件,然后构造一个新的提交以接管该提示更新后的git push文件的分支:

build.gradle

成为:

          o--...--o   <--branch1
         /
...--o--o--...--o   <--branch2
      \
       o--...--o   <--branch3

其中 o--...--o--X <--branch1 / ...--o--o--...--o--Y <--branch2 \ o--...--o--Z <--branch3 XY是添加到每个分支的新提交。现在,您可以一次推送所有这些新提交:

Z

它将把新的 commits 发送到服务器。只要您避免使用git push origin branch1 branch2 branch3 ,服务器的Git就会确保这些提交严格添加到其分支上,以便 server 的分支在其中增长。完全与您自己的分支机构成长相同。

请注意,如果在任何两个提交中基础文件的内容(--force文件)完全匹配,则这两个提交将共享保存这些内容的Git对象。这意味着进行几十个(“大约20个以上分支” )新提交仅占用很少的空间-提交的实际大小很小,因为文件被共享(此操作之所以可行,是因为一旦提交,便无法永远更改Git对象)。即使文件内容有所不同,一旦Git对象出现在Git的 pack文件中(这就是智能协议推送的工作方式),它们就会被高度压缩。

如果build.gradle的每个分支中确实具有相同的内容(这对我来说似乎不太可能),则可以使用简单的脚本将文件从其他分支复制到每个分支中并提交:

build.gradle

此循环按名称检出每个分支提示,从... build the base commit on some branch BR1, then: for branch in BR2 BR3 BR4 BR5 BR6; do git checkout $branch && git checkout BR1 -- build.gradle && git commit --reuse-message=BR1 || break done 的提示提交中提取build.gradle,并重新使用该提交中的提交消息进行提交。

如果文件(可能)不同,但想法是对每个文件应用相同的 change

BR1

这有点幻想:我们将for branch in BR2 BR3 BR4 BR5 BR6; do git checkout $branch && git cherry-pick BR1 || break done 提示中发生更改的内容转换为补丁(某种程度上,Git比BR1实用程序更聪明) )并将其应用于当前已签出的分支,并像以前一样重新使用提交消息进行新的提交。请注意,如果所有patch文件都相同,则此方法也适用。

如果过程的某些部分失败,这些shell脚本中的build.gradle行将使循环尽早终止。在这种情况下,您必须手动清理,然后使用剩下的分支重新启动循环以添加新的提交。