我有一个示例android项目存储库,我在其中为Android中的每个主题创建示例,并保留在不同的Git分支中,以便随时可以切换到相应的分支并获取特定主题的示例代码。
基本上,我在Git中只有一个Android项目,但是每个分支都有不同的代码库。目前我在那有20多个分支。
但是有些配置文件(例如build.gradle)保留了库版本,sdk版本等。这些文件无论任何分支,我都需要更新。
因此,每当我对此配置文件进行更改时,我都希望将其推送到所有分支,从而覆盖旧的配置文件。
说,如果要进行库更新,则在master
分支中更新版本并推送。但这仅影响客栈的master分支。
所有其余19个分支将具有旧版本代码。我将不得不切换到每个分支,并从master合并此配置文件。
是否有单个命令可以执行此操作?这样我可以在一个分支中更新文件,然后可以强制将其推到所有其他分支?
答案 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
,X
和Y
是添加到每个分支的新提交。现在,您可以一次推送所有这些新提交:
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
行将使循环尽早终止。在这种情况下,您必须手动清理,然后使用剩下的分支重新启动循环以添加新的提交。