【问题标题】:git - setting a commit's parent without rebasegit - 在没有变基的情况下设置提交的父级
【发布时间】:2011-05-09 00:17:52
【问题描述】:

我使用git-svn 创建了一个 SVN 存储库的 git 镜像。 SVN 内部的结构有点不规范,所以 git 创建了一个与 master 分支没有共同提交的分支。

      A---B---C topic

D---E---F---G master

我知道提交 A 是基于提交 E 并且我非常肯定我已经解决了导致 git 无法识别该事实的问题(使用 filter-branch)。我想要做的是将topic 重新附加到master 分支,将E 设置为A 的父级:

      A---B---C topic
     /
D---E---F---G master

git-rebase 似乎对我不起作用,因为提交A 的差异列出了master 中已经存在的大量文件的创建,从而导致大量冲突。
根据我对 git 的理解,只需将 E 设置为 A 的父级就足以解决所有问题。
这可能吗?如果是,我该怎么做?

【问题讨论】:

  • 有没有机会重新初始化 svn 的 git 镜像,将“分支”指向正确的目录?还是先修好svn结构?
  • 实际上 repo 确实使用了标准的trunk/tags/branches 布局。然而,我试图修复的分支是通过仅复制主干的子路径创建的 - 猜测这对于 git-svn 来说有点太多了。
  • rebase 有一个root 选项。如果需要,可以将其与 ontopreserve-merges 一起使用。

标签: git rebase


【解决方案1】:

看看grafts(可以在.git/info/grafts找到grafts文件)。格式很简单:

<commit sha1> <parent1 sha1> <parent2 sha1> … <parentN sha1>

这让 git 相信提交的父级与实际不同。使用 filter-branch 使移植物永久化(以便可以删除移植物文件):

git filter-branch --tag-name-filter cat -- --all

请注意,这重写了存储库的历史记录,因此不应在共享存储库上使用!


例如,如果您只想重写正在移植到 master 分支上的提交的历史记录,请使用以下命令:

git filter-branch --tag-name-filter cat -- master..

【讨论】:

  • 非必要时不要使用嫁接或过滤分支。
  • Grafts 在你需要它们时非常有用,但就像 git 中的其他一些特性一样,它们应该在你共享 repo 之前使用(或者你需要让其他人重新克隆)。正如答案所说,只需创建嫁接文件(A 哈希、空格、E 哈希、换行符)并使用“git filter-branch --tag-name-filter cat -- --all”重写历史记录而不更改其他提交数据
  • @JodaStephen 您应该将其添加到答案中。您是否知道如果存储库已发布,是否可以这样做,但您正在搞乱的移植只涉及新的、未发布的提交?
  • 直到 git 移植。谢谢!
  • 由于某种原因,最近的合并提交在我的仓库中缺少父级。这节省了一天。谢谢!
【解决方案2】:

根据您的图表(尽管我担心您所说的“我非常肯定我已经解决了导致 git 无法识别该事实的问题(使用 filter-branch)。”),您应该能够执行以下操作。

# checkout A
git checkout A

# Reset the branch pointer to E so that E is the parent of the next commit
# --soft ensures that the index stays the same
git reset --soft E

# Remake the commit with the E as the parent, re-using the old commit metadata
git commit -C HEAD@{1}

# Rebase the topic branch onto the modified A commit (current HEAD)
git rebase --onto HEAD A topic

【讨论】:

  • 几乎可以正常工作,但在该操作之后主题最终不会跟踪远程来源/主题!
【解决方案3】:

你只需要这个:

git rebase --root --onto master^^ topic^^ topic

root 选项允许您包含 A。

更新:

如果您想保留正在变基的部分的分支和合并,请添加 --preserve-merges 选项。

【讨论】:

  • 如果你有一个线性历史,这很好用,如果它有合并提交,你必须使用--preserve-merges,你必须手动重新解决合并冲突。
  • 是的。我会更新答案。还有一次我回答了同样的问题,我把这个选项也包括在内了。
  • @AdamDymitruk:关于您的回答的问题:您使用的是 Windows 吗? “^^”对我来说似乎很奇怪。那是父母的父母,还是第一个“^”是第二个“^”的DOS转义? (PS。如果是后者,那么git rebase --root --onto "master^" "topic^" topic 可能是更好的语法。)另一方面,由于使用--root,它可能确实是“祖父母”。谢谢。
  • 在 bash 中它是第一个父母的第一个父母
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-09
  • 2013-07-09
  • 1970-01-01
  • 2017-04-11
  • 2018-03-23
  • 2016-11-29
相关资源
最近更新 更多