我处于一个我Your branch is ahead of 'origin/master' by 2 commits.
的状态,因为我在编辑和提交之前忘记创建一个新的分支。
如何创建一个由这两个提交组成的新分支?
答案 0 :(得分:2)
您可以从当前的master
分支出来:
$ git branch my_new_branch
然后将master
重置为origin/master
:
$ git reset origin/master --hard
答案 1 :(得分:2)
Mureinik's answer是正确的(并且被投票赞成),但这可能有助于对这里发生的事情进行一些视觉说明。
在Git中,从某种意义上说,分支名称并不真正意味着。他们所做的是“指向”(包含原始的commit-hash-ID)一个特定的提交。这是重要的提交本身。提交是(大多数)永久性的和(完全)不可更改的:一旦生成,其哈希值为deadc0ffee...
或其他的提交就是永久提交。但是master
或branch
:这些这样的名称可能会发生变化。
与此同时,每次提交都会“指回”(存储其丑陋的哈希ID)以前的提交。因此,如果你在master
并且有一系列提交 - 而不是写出大丑陋的哈希ID,我们将在这里使用单个字母 - 它们看起来有点像这样:
... <--E <--F <--G <-- master
由于内部箭头无法更改,并且始终指向后方,我们可以像这样绘制它们:
...--E--F--G <-- master
现在,如果您添加新提交,它将返回master
的上一个提示,master
将指向它:
...--E--F--G--H <-- master
然后你做第二个:
...--E--F--G--H--I <-- master
请注意,master
只是不断前进,因为我们添加了更多提交。但是origin/master
之前指的是G
,现在仍然如此,所以我们真的应该这样做:
...--E--F--G <-- origin/master
\
H--I <-- master
此时您要做的是创建新名称newbranch
或feature
或其他任何内容,指向提交I
:
...--E--F--G <-- origin/master
\
H--I <-- master, newbranch
然后“重新设置”master
,使其回到G
:
...--E--F--G <-- master, origin/master
\
H--I <-- mewbranch
您可以使用git reset
执行此操作。
git reset --hard
现在,这些绘图很好 - 它们是记住提交发生了什么的好方法 - 但它们没有考虑索引和< EM>工作树的。 Git的索引是一个复杂的小东西,位于当前提交和工作树之间;它可能最好被描述为“你构建 next 提交的地方”。同时,工作树只是“你工作的地方”:你需要这个,因为Git的存储 - 包括Git索引的存储 - 是Git自己的,特殊的,压缩的Gitty格式,机器上几乎没有任何其他命令可以处理。
当你使用git reset
时,你有Git做三个的事情:
master
以使其指向某个任意其他提交; 第1步是非常安全的,因为提交(大部分)是永久性的并且(完全)只读:移动分支名称不会以任何方式损害提交本身。你可以把它移回去,然后又回来了。
步骤2和3不太安全。 --hard
重置会擦除您的工作树,将其更改为与您重新设置的提交相匹配。你做过的任何你没有做过的工作,此时可能会丢失。 (如果你已经提交了它,当然,Git已经永久保存了它。好吧,大多是永久性的。 Reachable 提交是永久性的,但那是另一个话题。)
同样,--hard
或甚至--mixed
重置会重新设置索引。在你开始使用索引进行高级技巧之前,这并不重要,因为索引中的内容将是提交中的内容 - 这是它的开头 - 或者从工作树复制到索引中的内容,使用git add
。因此,这是工作树,因此--hard
是这里最关注的问题。
这个的简短版本,如果还不晚,:-)是:在使用git reset --hard
之前确保您的工作已提交或不需要。(如果您不喜欢我真的想在一个分支上提交它,但不想丢失它,你可以使用git stash
来保存它。这使得一个提交 - 好吧,真的,在至少两个提交 - 但git stash
提交的提交在 no 分支上,这有点奇怪。)