有什么办法让git将master中的文件添加到其他10个分支中?

时间:2018-09-14 14:16:42

标签: git

有没有办法告诉git将新文件添加到其他每个分支中?

不是每个分支都使用git checkout <branch>; git merge master,而是在下面的每个分支中添加 newfile 的快捷方式吗?

     master
       +-----newfile
       |
      --- 
    /  |  \
   /   |   \
  /    |    \
foo   bar   baz

编辑:这是我想出的bash脚本(如果实施,则需要一些清理),但希望有更好的方法。

MSG='added newfile which contains a method to workaround issue IS-797'
for branch in $(git branch | grep -v master | sed 's#^[ *\t]##g'); do
   echo merging into $branch
   git checkout $branch && git merge master -m "$MSG"
done

3 个答案:

答案 0 :(得分:5)

有两种方法可以解决此问题。在我看来,其他评论/答案中的大多数建议(截至撰写本文时)都令人怀疑。这是各种选项的优缺点。

首先,对于最终历史记录,至少有三个不同的选项。每个都有优点和缺点。有点。更像每个人都有缺点,而优点是它没有其他方式的缺点。

  • 自从创建受影响的分支之前,文件就好像在“始终存在”。不利的一面是,这是历史记录的重写,并且会带来后果。

  • 看起来文件是由每个分支独立添加的。该文件可能会以难以阅读的历史记录结尾,并且有很多可能避免的合并冲突。但是,它不会重写历史记录。

  • 看起来文件被添加一次,然后合并到每个分支中。有些人真的讨厌合并提交,甚至当某些人不是特别讨厌合并提交时,我认为这种方法会导致混乱的分支拓扑。但是,它避免了历史记录的重写,并且可以很好地运行。即,从功能上讲,这是最干净的选择,但从美学上来说却很粗糙。

详细查看每一个:


重写历史记录

如果您一个人使用仓库,并且从未做过任何使您现有的提交ID(“哈希”)重要的事情,那么这是一个相当有吸引力的选择。即使您共享该存储库,只要您与该存储库的其他用户协调,就可以使该工作正常进行。

对于大的重写,我的一般建议是与所有人协调,以设定将所有工作推送到仓库的日期/时间。然后每个人都丢弃其克隆,进行重写,然后每个人都重新克隆。如果这不切实际,那么进行大量重写可能不是一个好主意。但是,无论如何,如果要考虑使用它,请阅读git rebase文档中的“从上游基础恢复中”,以获取有关将要发生的事情的更多信息。

我想rebase是重写历史记录的原型方法,在这种情况下,几乎可以肯定这是错误的方法。如果您有很多分支,则必须执行多次。如果您有复杂的历史记录,则很难正确地进行处理。特别是它不能很好地处理合并(即使是最近添加的改进)。

您可以使用git filter-branch。最简单的方法是使用--tree-filter。您可以将文件的副本放在工作树之外的某个地方,然后

git filter-branch --tree-filter 'cp /path/to/stored/copy/of/file path/to/file/in/worktree' -- --all

然后filter-branch将继续检查历史记录中的每个提交,运行cp命令以将该文件添加到该提交的工作树中,并写入包含结果内容的新提交。然后它将分支从旧提交移动到新提交。如果您有标签并且也希望它们移动,请添加一个--tag-name-filter参数,例如

git filter-branch --tree-filter 'cp /path/to/stored/copy/of/file path/to/file/in/worktree' --tag-name-filter cat -- --all

问题是,如果您的历史记录很大,则过程很慢。您可以通过在工作树中使用ramdisk(请参见-d选项)或使用--index-filter而不是--tree-filter来加快速度(但这需要您使用其他命令)直接更新索引,并不是那么简单)。


每个分支添加文件

这就是cherry-pick会带给您的。由于问题是关于如何使过程自动化,因此尚不清楚为什么有人用cherry-pick来评论,好像这是一个解决方案。该过程与合并一样手动(并且可以编写脚本)。

唯一的区别是,当您这样做时,git会创建独立的提交,分别将文件添加到每个分支上。

您可以使用与合并时相同的基本脚本,只需将merge命令替换为cherry-pick命令即可​​。


合并

为此,您已经制定了一个合理的解决方案-您需要一个脚本。我唯一要注意的是,git for-each-ref通常比git branch更适合用于输入脚本。 https://git-scm.com/docs/git-for-each-ref

答案 1 :(得分:0)

您可以使用git rebase来实现它,但请务必阅读为什么不应该使用this article中的git rebase

答案 2 :(得分:0)

如果您已经在master上进行了提交,那么我将在每个分支上简单地选择它。这似乎是迄今为止编写起来最简单,最可靠的脚本。一个分支的故障对于其他分支来说应该是无关紧要的。

commit='deadbeef'
for branch in $(git branch | sed -n '/master/!s#^[ *\t]##p'); do
   echo "cherry-picking onto $branch"
   git checkout "$branch" && git cherry-pick "$commit"
done

顺便说一句,注意小写的shell变量的首选项,如果您只希望每行有一个匹配项,则不要在g中使用sed标志,并避免使用{{3 }}。

在sed脚本中使用\t并非完全可移植;也许尝试使用[*[:space:]]而不是[ *\t]

挑选单个提交的樱桃当然比将所有master合并到每个分支中更为具体,这对那些为此苦苦挣扎的人来说是完全不可以的。

相关问题