【问题标题】:How to push a specific commit to a repo, not including the previous commits, without the history?如何在没有历史记录的情况下将特定提交推送到仓库,不包括以前的提交?
【发布时间】:2020-03-22 20:26:10
【问题描述】:

我正在尝试将特定提交推送到 upstream 存储库,这与我正在处理的相同,但略有更改。

当前的 repo 领先于 upstream ,我想推送我在当前 repo 中所做的一些更改,但不是全部。

当我做类似的事情时

git push upstream <commit SHA>:<remotebranchname>

它有效,但它也会推送在我的 upstream 存储库中的最后一次提交和我正在推送的提交之间完成的所有其他提交。

然而,我希望只推送在那一次提交中所做的更改,而不是在那次提交之前所做的更改。

如何避免它们被整合?

更新给出的答案解释了如何推送特定的提交(之前的所有历史记录),但我想只推送特定的提交,没有背后的历史记录.

【问题讨论】:

  • 尝试从上游签出一个分支,挑选你想要推送的提交。使 --set-upstream 到您想要将提交推送到或进行 PR 的任何分支

标签: git commit git-commit upstream-branch


【解决方案1】:

为了避免推送某些更改,您的分支应设置为您想要包含的最后一次提交。在您的情况下,最好的选择是创建一个新分支,将其重置为您想要包含的最后一个提交,挑选您想要推送的一个提交并推送。

git checkout -b new-branch # make sure to do this **while you're on** the upstream branch
git pull <remote> <upstream branch> #just to be sure you're right where the remote upstream branch is
git cherry-pick <commit hash>
git push <remote> new-branch

【讨论】:

  • 嗯...我真的不明白...所以当我在我的current repo 中时,我需要创建一个新分支,然后获取提交并将其推送到upstream?但是为什么在你的例子中它写成remote
  • 当我这样做的时候,因为我的提交是祖先,所以它不会恢复到那个提交,所以我基本上上传了所有当前的更改。
  • 您提到的 @DmitryParanyushkin upstream 必须是特定遥控器的名称。如果我理解正确,您希望在上游分支之上应用特定提交 将您推送到您的另一个分支的提交,这是正确的吗?如果没有,您能否制作一个提交流程图,以便更容易理解?
【解决方案2】:

您首先必须使您的本地历史看起来像您想要推送的内容。然后就可以推送了。

上千种可能的方法之一是使用 git rebase,例如:

git rebase -i upstream/remotebranchname

将向您显示一个编辑器窗口,其中包含您所做的尚未推送的提交列表以及一个小文档要做什么。只需保留您想要推送的提交的行不变,但删除您不想推送的行。然后保存退出。希望您不会有冲突(在您想要的提交中更改文件在您不想要的提交中)。

然后你就可以推送了。

(如果您想在本地保留不想推送的提交(无论出于何种原因),请首先制作例如标签:

git tag usefultagname

【讨论】:

  • 是的,但是在这种情况下,比如说,我恢复到那个提交,我也会推送那个提交背后的所有历史。而且我只想推送在该提交中所做的更改。
  • 不,如果你 rebase 到远程分支,你会得到你选择的提交。
  • Git 将总是推送完整的历史缺失部分。不推送提交的唯一方法是在推送之前将它们从本地历史记录中删除。
  • 这不是真的。您可以调整 git,使其仅推送某个提交。例如,使用cherry-pick
  • @DmitryParanyushkin:注意git push 不会推送更改。它推动提交。 Git 提交不是变更集;它们是快照和元数据。
【解决方案3】:

这是禁止的。

Git 提交包括其父哈希 ID。如果您作为发送者,向另一个 Git 提供提交 H(对于某些哈希 ID H),那么其他 Git 不需要接受 H,直到它还有 H 的父级(或父级,如果是合并提交)。所以你必须提供 H 的父母。它不需要接受该提交,直到它依次拥有 那个(或那些)提交的父级,依此类推。

换一种说法,提交的 ID 就是它的哈希值,但是对于 拥有,在存储库中提交意味着您还拥有 它的所有祖先1 因此,处理此类提交的唯一方法是拥有其所有祖先。

此时,您可以制作该提交的副本(例如,通过git cherry-pick)以获取具有不同不同提交em> 哈希 ID、不同的父级以及由于这个不同的父级而您可能想要的任何其他差异。2 然后您可以交付这个 不同 提交(通过其不同的哈希ID) 到其他一些 Git 存储库。如果该其他 Git 存储库确实具有此新副本的父级,则它们不会首先要求任何其他提交。


1此规则在浅层克隆中有所放宽,并且正在进行以其他方式放宽它的工作,但至少原则上仍是必需的。 没有有其祖先的提交至少是可疑的;可能是假的;链的完整性是由沿着链一路回到根来确定的。

2特别是,您可能还需要不同的快照。请记住,Git 提交保存 快照——每个文件的完整副本——而不是变更集。因此,如果要将提交H 的副本H' 应用于提交B,那么您想要在H' 中的不是H 中的快照,而是由 生成的快照更改 H 进入一个变更集,然后应用该变更集提交B,同时考虑任何其他差异在H 的父级和B 之间也是如此。要将 H 更改为变更集,我们(或 Git)会将其快照与其父级快照进行比较。

git cherry-pick 命令是一个工具,用于在签出提交 B 时从 H-and-its-parent 生成 H'。)

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 2022-11-24
    • 2015-09-14
    • 2011-03-14
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    相关资源
    最近更新 更多