简体   繁体   English

有没有办法将第二根附加到git中的任意提交?

[英]Is there a way to attach a 2nd root to an arbitrary commit in git?

We didn't import our entire history when moving to git, and is making some operations difficult without the history of some of the files. 转移到git时,我们并没有导入整个历史记录,并且如果没有某些文件的历史记录,将会使某些操作变得困难。 I was thinking of importing some of the history into our tree using an orphan branch and then somehow attaching it to the root node. 我当时正在考虑使用一个孤立分支将一些历史记录导入我们的树中,然后以某种方式将其附加到根节点。 Is that possible? 那可能吗? I realize I could attach it to a later one using a merge, but I was wondering if it could be done to somehow keep the original history timeline intact. 我知道我可以使用合并将它附加到以后的一个,但是我想知道是否可以这样做以保持原始历史记录的时间完好无损。

There are a few options. 有一些选择。 Which is best depends on your needs, certain other users' belief that they can tell you which is best notwithstanding. 哪一个最好取决于您的需求,尽管某些其他用户相信他们可以告诉您哪个是最好的。

Option 1: You can use git filter-branch with a parent-filter to graft the current root onto the newly-imported history. 选项1:您可以将git filter-branchparent-filter以将当前根嫁接到新导入的历史记录上。 This is a "history rewrite", so it requires coordination with all developers. 这是“历史记录重写”,因此需要与所有开发人员协调。 My preferred way to do mass rewrites is: 我进行批量重写的首选方式是:

  1. Everyone pushes all of their code. 每个人都推送他们的所有代码。 (It doesn't have to be merged, but has to be in the remote somewhere.) (它不必合并,而必须在远程某处。)
  2. Everyone discards their clones 每个人都丢弃他们的克隆
  3. You import the history and perform the rewrite 您导入历史记录并执行重写
  4. Everyone makes new clones from the rewritten repo 每个人都从重写的仓库中创建新的克隆

Of course that kind of coordination may not be practical for your team. 当然,这种协调对于您的团队可能不切实际。 You could go ahead and do the rewrite, and just let everyone know that they have to recover all of their branches; 可以继续进行重写,然后让所有人都知道他们必须恢复所有分支。 but that's tedious, and it only takes one developer messing it up to potentially undo your rewrite work. 但这很乏味,并且只需要一名开发人员将其弄乱就可以撤消重写工作。

Also be aware all commits' IDs will change; 另外请注意,所有提交的ID都会更改; so even if you can coordinate the cut-over, if you use those commit IDs (in release documentation, for example) then a rewrite may not be your best option. 因此,即使您可以协调转换,但如果使用这些提交ID(例如,在发行文档中),则重写可能不是最佳选择。

For information on this option, see the git filter-branch docs ( https://git-scm.com/docs/git-filter-branch ); 有关此选项的信息,请参见git filter-branch docs( https://git-scm.com/docs/git-filter-branch ); the parent-filter examples cover what you need. parent-filter示例满足了您的需求。

As an aside, this is the closest thing to a "rebase" type solution that makes any sense at all. 顺便说一句,这是最根本没有任何意义的“ rebase”类型解决方案。 You can't easily rebase any but the simplest of histories, and rebase would re-calculate the content of each commit (which serves nothing but to create an opportunity for mistakes, since you don't actually want your commits' content to change). 除了最简单的历史记录之外,您无法轻松地重新设置基准,而重新设置基准将重新计算每个提交的内容(除了实际上不希望更改您的提交内容之外,它只能提供犯错的机会) 。

Option 2: You could use git replace to "paper over" the break in history. 选项2:您可以使用git replace来“覆盖”历史记录中的中断。 The best way to do this is to have one commit of "overlap"; 最好的方法是一次提交“ overlap”。 so import history up to and including a commit that's equivalent to your current root. 因此,请导入历史记录,直到(包括)与您当前根目录相同的提交为止。

This avoids the history rewrite, but it doesn't propagate between clones and remotes; 这样可以避免重写历史记录,但是不会在克隆和远程之间传播。 so each user would have to set it up locally in each clone. 因此,每个用户都必须在每个克隆中在本地进行设置。 That's ok I guess; 我猜没关系; you could just set it up when you need it. 您可以在需要时进行设置。 But also be aware, there are some known quirks/bugs related to replace . 但也要注意,有一些与replace有关的古怪/错误。 See the git replace docs. 参见git replace docs。

What I would do if pursuing this is to import the history, tag its tip, and put a note on the existing root with instructions on how to set up replace if needed in a given clone. 如果要执行此操作,我将要做的是导入历史记录,标记其提示并在现有根目录上添加注释,其中包含有关如何在给定克隆中设置替换的说明。

Option 3: merge . 选项3:合并 This isn't really an option within your constraints, but worth pointing out the pros and cons. 这是不是真的是你的约束中的一个选项,但值得指出的利弊。

As you note, you can merge the imported history to your branch tip(s). 如您所述,您可以将导入的历史记录合并到分支提示中。 The resulting history will not look quite normal, but at least the history will be there. 产生的历史记录看起来不太正常,但是至少历史记录会存在。 You have to tell git to --allow-unrelated-histories , and you'll merge with the ours strategy (because you don't actually want the merge to change anything on your branch). 您必须将git告诉--allow-unrelated-histories ,然后将与ours策略合并(因为您实际上不希望合并更改分支上的任何内容)。

This sticks with very basic functionality of git, and doesn't rewrite any refs' histories, so it's simple and reliable. 这坚持了git的非常基本的功能,并且不会重写任何裁判的历史记录,因此它既简单又可靠。 But I for one would not look forward to navigating a history that was stitched together in that way. 但是我永远都不希望浏览以这种方式缝合在一起的历史。 IMHO it would be just as well to leave the histories separate (even if you import the old history into the same repo as an orphan), but again only you can determine how the pros and cons weigh for your team. 恕我直言,最好将历史记录分开(即使您将旧的历史记录作为孤儿导入到相同的仓库中也是如此),但同样只有您可以确定团队的优缺点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM