致力于掌握分离的HEAD

时间:2016-12-30 07:10:39

标签: git github

昨晚我编码很晚,犯了一个致命的错误。我在一个分支上并在较早的提交上运行git checkout。然后我开始编写代码。推送到git master需要哪些步骤?

要明确:我想将我在计算机上本地保存的回购推送到主要来源。

谢谢!

3 个答案:

答案 0 :(得分:2)

存储您的更改,切换回母版并在那里应用更改,然后继续您的工作:

git stash save
git checkout master
git stash pop

之后,您可以在需要时执行git addgit commit,它将位于主分支之上。

答案 1 :(得分:2)

假设分离的HEAD是您想要master的位置(即您在master中没有要保留的任何提交,也没有任何已修改的文件工作目录)您可以移动 master分支,使用git branchHEAD选项指向--force引用的提交。

来自the documentation

  

<强> -f
  的 - 力
  重置&lt; branchname&gt;到&lt; startpoint&gt;如果&lt; branchname&gt;已存在。没有-f git branch 拒绝更改现有分支。

在您的情况下,您只需说:

git branch -f master HEAD

然后你可以结账master并像往常一样将提交推送到远程master分支:

git checkout master
git push origin master

同样,作为评论中的@torek pointed out,此解决方案假定您希望重置 master分支到HEAD引用的提交,不关心当前可以从master到达的任何提交。

答案 2 :(得分:2)

从您的问题中不清楚您是否制作了新的提交

根据您的具体情况,有三件事要做:

  • 使用git checkout -b newbranch然后重新定义或合并
  • 只是git checkout master,如果可以的话(但见下文)
  • 使用git stash,然后git checkout master,然后git stash apply,最后git stash drop

使用哪一个主要取决于您是否已经提交了新的提交。

必要的背景信息

当您在自己的本地存储库中工作,编辑文件并准备进行新的提交时,实际上只有三件事情是重要的:

  • 您当前的提交,a.k.a。,HEAD
  • 您当前的工作树。工作树是您工作的地方:编辑文件以修改它们,创建新文件或git rm来自工作树的一些现有文件......
  • 您当前的索引。索引是构建 next 提交的位置:每次运行git add时,都会将工作树中的文件复制到索引中。这将更新其中已存在的文件,或将其添加为新文件。运行git rm时,将从索引中删除该文件。

如果您提交了

如果您进行了新的提交,则会创建一个新的分支,并且&#34;分离的HEAD&#34;只是意味着你的新分支没有名字

最终,当您决定准备好事情时,请运行git commit。通过将索引(已添加,更新和/或删除某些文件)转换为保存的工作树快照,您可以在以后根据需要再次查看,从而进行 new 提交。它将您的日志消息写入提交,将当前提交写为新提交的父级&#34;,然后写入 new 提交& #39; s ID - 大丑陋的SHA-1,deadc0decafe...或其他什么,进入分支。

通常,&#34;在分支上&#34;例如,新提交的ID所在的位置是分支名称

在&#34;分离的HEAD&#34;但是,没有分支名称,因此新提交的ID直接进入HEAD

我们可以像在分支上绘制任何提交一样绘制它:

...--o--o--o--o--o   <-- master
         \
          o   <-- HEAD

这是你在&#34;分离的HEAD&#34;中提交的内容。 mode:您的新提交位于新分支上。它没有名字。如果你做了多次提交,他们就像往常一样串起来:

...--o--o--o--o--o   <-- master
         \
          o--o--o   <-- HEAD

如果您处于这种情况,您只需要为您的分支命名。只需运行git checkout -b newbranch即可创建名为newbranch的新分支(放入你喜欢的任何名字,现在你所做的所有提交都在新的分支上。

进入正常的命名分支后,您可以使用所有常用方法将这些提交带入主线,例如使用git rebasegit merge

如果您还没有提交

如果你有做出任何新提交,那么你可能会非常幸运。 您可能只能git checkout master注意:不要使用--force

同样的规则适用于以前,有三件事情很重要:您当前的(HEAD)提交,您当前的工作树和您当前的索引。但是现在我们进入Git的一个有趣的部分: git checkout如何进行变更。如果你尝试git checkout master,Git会做的是将当前提交 - 分离的HEAD - 与master上的提示提交进行比较。

让我们再次绘制原始提交链,但使用HEAD标记*,并使用X向主提交提示:

...--o--*--o--o--X   <-- master

问问自己:如果你是Git,并且你试图从HEAD移动到master的尖端,知道作为Git,你可以非常在任何两次提交中轻松告诉哪些文件是相同的,哪些是不同的...什么是最快,最简单,最懒惰的方式从*移动到X

请记住, index 会记录 next 提交内容,因此它开始持有*中的内容(因为您选中了)那个早些时候)。工作树也开始持有*中的内容。如果这些都没有改变,那么从*转移到X的最快最容易最懒的方法是:只在索引和工作树中替换不同的文件

这里的棘手问题是偶数 - 或者我应该说,尤其是 - 如果你已经在索引和/或工作树中进行了更改,Git 仍然做同样的事情。它会尝试将所有修改保留在原位。如果(并且仅当)您在当前提交*和新目标X中更改的文件相同,可以执行此操作。它只需要换掉&#34;从 - *更改为 - X&#34;文件(在索引和工作树中),所以它只留下其他一切。 (另见Git - checkout another branch when there are uncommitted changes on the current branch。)

在这种特殊情况下,正在运行git checkout master重新连接您的HEAD,使您当前的提交成为master的提示,包含所有与您一起变化 - 现在您可以git commit,或继续编辑,或其他任何内容。

如果git checkout抱怨怎么办?

如果git checkout master说它不能这样做 - 它会覆盖你的文件 - 那么你只有一个合理的选择,就是提交它们。但是,您可以通过git stash命令使用快捷方式提交。

git stash save实际上做了一些提交,一个用于索引,一个用于工作树。 1 但是他们&#39;重新提交 on no branch 。完成这些提交后,stash命令会清除索引和工作树,以便它们与HEAD提交匹配。您现在可以git checkout进行其他一些提交 - 例如master的提示 - 然后应用已保存的存储

git stash apply

在内部,应用保存的存储有点复杂,因为它不止一次提交。但是,出于这个特殊目的,你可以忽略所有这些:简单地应用&#34; smooshes up&#34;提交并尽力使相同的更改为新的当前提交,即master的提示。

apply步骤使用内部合并代码,就像rebase复制提交时git rebase一样。这意味着您可能最终必须解决合并冲突。如果你想关闭它,你可以中止使用藏匿的尝试,并且由于申请没有丢弃藏匿,它仍然在那里,你可以在以后申请,或将其变成自己的分支。

如果申请顺利,但通常情况确实如此 - 现在git stash drop存储安全了。如果您运行git stash pop,则会结合应用步骤和放置步骤。我建议保持它们分开,以防你改变主意 - 一旦掉线,应用的藏匿很难恢复。 2 当然,不是每个人都像我一样谨慎git stash pop是非常安全的:例如,如果它没有正确应用,那么它不会删除存储。

1 通常,它只是这两个提交,但是对于-u-a,它会使三个提交。这些提交具有合并的形式,因此只需要一个Git 引用来记录它们,但它们在任何意义上都不是正常的合并。

2 由于它们是提交,它们可以恢复一段时间 - 但由于隐藏提交在 no 分支上,所以通常的方法都不起作用,并且通常的30天保证根本不起作用。