1

我对 Git 很陌生,我认为我在我的主分支中造成了混乱。

这是发生的事情:

我正在工作(和平地,不惹任何人),我得到了这样的承诺。

a --> b --> C --> D

a, b成为其他人的承诺,CD成为我的承诺。我将所有内容推送到我们的主存储库,并且我们必须在每次推送时运行测试的自动工具说构建失败。所以我惊慌失措。我创建了一个新目录并重新克隆了存储库,直到提交b(当那个自动化工具说构建正常时)进行了一些非常小的更改并强制推送(是的,我不是很聪明,但是已经晚了,我吓坏了)所以那时,远程存储库看起来像这样:

a --> b --> E

但事实证明,我最初的提交是正确的,CD失败的是自动化工具。它给出了误报!当我意识到有人再次提交到主分支(远程存储库)时,此时它看起来像这样。

a --> b --> E --> f

我想要做的是安全且不破坏我同事的工作,将我良好的提交插入CD分支中。我的计算机目录中仍然有这些提交,但是一旦我执行 a git pull,它们就会被销毁。

我希望远程存储库看起来像:

a --> b --> C --> D --> f

或者

a --> b --> f --> C --> D

甚至

a --> b --> E --> f --> C --> D

(保持超级虚拟提交E,我不介意)

基本上,我想要在那里,CD不会破坏我同事的f承诺。

这甚至可能吗?

我处于恐慌模式,所以任何事情都会有所帮助。

4

2 回答 2

1

做就是了:

git pull --rebase

请注意,“git pull”不会破坏您的本地提交,它会创建一个合并,这可能不是您想要的。

于 2013-09-29T06:10:44.067 回答
0

您可以获取CD返回[编辑:如果您在原始存储库中“丢失”了它们,但我看到您没有]。使用git reflog通过 ID 查找它们:

$ git reflog

或者:

$ git reflog master

(如果您在上master并且只想查看那里发生的更改)等。

找到 commitD后,在其上粘贴分支标签。假设上面的输出清楚地表明这HEAD@{3}是您想要的。然后:

$ git branch recover_my_stuff 'HEAD@{3}'

或者:

$ git branch get_d_back 0123456

按数字(并使用不同的名称等)来完成。您可以在此之前运行gitk HEAD@{3}and或等,以仔细检查这是否是您想要的。一旦你有一个分支标签,它会再次显示给你。gitk 0123456git log HEAD@{3}git branchgitk --all


编辑:因为您仍然在原始仓库中拥有它们,所以让我们在那里工作。首先,您master当前有a - b - C - D序列。让我们将此分支重命名为temp,然后使用git fetch以获取远程 repo 的最新信息,并创建一个新master的 track origin/master

$ git branch -m master temp
$ git fetch origin
$ git checkout -b master --track origin/master

(这里,temp——因为它只是对原始文件的重命名——也会master“跟踪” origin/master,所以 git 会告诉你它与 不同origin/master,在多次提交之前和之后。但你不需要关心,你可以忽略这些来自 git 的通知。如果你愿意,你可以通过编辑 git 配置让它停止“跟踪”,但无论如何它都是无害的。)


好的,所以,假设您已经完成了上述操作,gitk现在显示(以更漂亮的图形形式)这个。我将为temp恢复的东西使用分支标签,并假设其余的都打开了master(好吧,你说它是 :-)):

a - b - E - f         <-- HEAD=master, origin/master
      \
        C - D         <-- temp

一般来说,在其他人身上“倒带”分支标签是不好的(可以对自己做 :-))所以让我们留在那儿E。您可以在任何时候git revert添加一个简单地取消所做的提交的提交EC您现在需要做的D就是移植f. 这就是这样git rebase做的:它将原始提交中的更改复制到新提交中。然后它移动标签。

$ git checkout temp
$ git rebase master

现在你会有这个:

a - b - E - f         <-- master, origin/master
     \       \
      \       C'-D'   <-- HEAD=temp
       \
        C - D          [no branch label]

(由于 C 和 D 没有标签,它们将从gitk --all.

现在您所要做的就是提出master来,您可以使用git merge. 首先你必须git checkout master(有一种方法可以在没有中间步骤的情况下做到这一点,但让我们保持简单):

$ git checkout master

a - b - E - f         <-- HEAD=master, origin/master
             \
              C'-D'   <-- temp

这是相同的提交图,我们只是更改了 HEAD 指向(到 master)的位置并删除了不可见的提交。

$ git merge temp

merge操作将“快进”主控,因为实现合并所需的唯一事情是将标签从提交“向下滑动”f到提交D'

a - b - E - f         <-- origin/master
             \
              C'-D'   <-- HEAD=master, temp

现在您可以git branch -d temp删除临时分支并git push origin master推送。


旁注:恭喜您绘制了提交图现在看起来像什么的清晰示例,以及您希望它看起来像什么。这大约是确定要使用哪些 git 命令所需的所有工作的 80%。:-)

于 2013-09-28T16:12:22.977 回答