git - tutorial - 我怎样才能调和分离的HEAD与主/来源?




git中文 (16)

让你的分离提交到它自己的分支

只需运行git checkout -b mynewbranch

然后运行git log ,你会在这个新的分支上看到这个提交现在是HEAD

我是Git分支复杂性的新手。 我总是在单个分支上工作并提交更改,然后定期推送到我的远程原点。

最近,我做了一些文件的重置,让它们脱离了提交阶段,后来又做了一次rebase -i来摆脱最近的一些本地提交。 现在我处于一个我不太明白的状态。

在我的工作区域, git log显示了我期望的内容 - 我在正确的列车上提交了我不想去的地方,以及那里的新地方等。

但是我只是推到了远程仓库,那里有什么不同 - 我在rebase中杀死的一些提交被推迟了,而在本地提交的新提交不在那里。

我认为“master / origin”与HEAD是分开的,但我不清楚这意味着什么,如何使用命令行工具将其视觉化,以及如何修复它。


今天我遇到了这个问题,我更新了一个子模块,但没有在任何分支上。 我已经承诺,所以藏起来,结帐,摆动不起作用。 我结束了樱桃采摘脱离头部的承诺。 所以我立即承诺(当推失败时),我做了:

git checkout master
git cherry-pick 99fe23ab

我的想法是:我在一个独立的头上,但我想成为主人。 假设我的分离状态与主人没有太大区别,如果我可以将我的承诺应用于主人,我就会被设置。 这正是樱桃选择所做的。


你所要做的就是'git checkout [branch-name]',其中[branch-name]是你进入独立头部状态的原始分支的名字。 (从asdfasdf分离)将消失。

因此,例如,在分支'dev'中签出提交asdfasd14314 - >

'git checkout asdfasd14314'

你现在处于独立的头部状态

'git分支'会列出类似于 - >的内容

* (detached from asdfasdf)
  dev
  prod
  stage

但要摆脱分离的头部状态并回到开发 - >

'git checkout dev'

然后'git分支'将会列出 - >

* dev
  prod
  stage

但是,当然如果你不打算保持分离头部状态的任何变化,但是我发现自己做了这么多事情并不打算做任何改变,只是看看以前的提交


只要这样做:

git checkout master

或者,如果您有想要保留的更改,请执行以下操作:

git checkout -b temp
git checkout -B master temp

在这里寻找分离头部的基本解释:

http://git-scm.com/docs/git-checkout

命令行可视化它:

git branch

要么

git branch -a

你会得到如下输出:

* (no branch)
master
branch1

* (no branch)表明你处于分离的头部。

您可以通过执行git checkout somecommit等来达到此状态,并且它会通过以下方式警告您:

你处于'分离头部'状态。 您可以环顾四周,进行实验性更改并提交它们,并且可以放弃您在此状态下进行的任何提交,而不会通过执行另一个结帐影响任何分支。

如果你想创建一个新的分支来保留你创建的提交,你可以(现在或以后)再次使用-b和checkout命令。 例:

git checkout -b new_branch_name

现在,让他们掌握主人:

做一个git reflog ,甚至只是git log并记下你的提交。 现在, git checkout mastergit merge提交。

git merge [email protected]{1}

编辑:

要添加,使用git rebase -i不仅可以删除/终止您不需要的提交,还可以编辑它们。 只需在提交列表中提及“编辑”,您就可以修改您的提交,然后发出git rebase --continue - 继续前进。 这可以确保你永远不会遇到分离的头部。


如果你在主控制器上做了一些提交并且只想在那里“向后合并” master (即你想让master指向master ),那么单线程将是:

git checkout -B master HEAD
  1. 这创建了一个名为master的新分支,即使它已经存在(这就像移动master ,这就是我们想要的)。
  2. 新创建的分支设置为指向HEAD ,这是您的位置。
  3. 新分支已经签出,所以你之后会成为master

我发现这在子存储库的情况下特别有用,它也经常处于分离状态。


如果你在eclipse中使用egit:假设你的主人是你的主要开发分支

  • 将更改提交给分支,通常是新分支
  • 然后从遥控器拉出
  • 然后右键单击项目节点,选择团队,然后选择显示历史记录
  • 然后右键点击主人,选择退房
  • 如果日食告诉你,有两个主人一个本地一个远程,选择远程

在此之后,您应该能够重新连接到原点主人


如果你完全确定HEAD是一个很好的状态:

git branch -f master HEAD
git checkout master

你可能无法推到原点,因为你的主人已经偏离了原点。 如果您确定没有其他人使用回购,您可以强制推送:

git push -f

如果您在功能分支上没有其他人正在使用,那么这将非常有用。


对我来说,就像再次删除本地分支一样简单,因为我没有任何我想推送的本地提交:

所以我做到了:git branch -d branchname

然后再检查分支

git checkout branchname


当我个人发现自己处于某种情况时,当我不在master身上时,我做出了一些更改(例如, HEAD被分离到master之上,并且两者之间没有任何提交),存储可能会有所帮助:

git stash # HEAD has same content as master, but we are still not in master
git checkout master  # switch to master, okay because no changes and master
git stash apply  # apply changes we had between HEAD and master in the first place

我进入了一个非常愚蠢的状态,我怀疑其他人会发现这个有用的......但以防万一

git ls-remote origin
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        HEAD
6f96ad0f97ee832ee16007d865aac9af847c1ef6        refs/heads/HEAD
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        refs/heads/master

我最终修正了这个问题

git push origin :HEAD

我遇到了同样的问题,我通过以下步骤解决了这个问题。

如果你需要保持你的改变

  1. 首先,您需要运行git checkout master命令将您恢复到主分支。
  2. 如果您需要保持更改,请运行git checkout -b changesgit checkout -B master changes

如果你不需要你的改变

  1. 要从分支中删除所有未跟踪的文件,请运行git clean -df

  2. 然后,您需要清除存储库中所有未分离的更改。 为了做到这一点,你必须运行git checkout --

  3. 最后,你必须使用git checkout master命令将分支放回主分支。


正如Chris所指出的那样,我有下面的情况

git symbolic-ref HEAD失败并fatal: ref HEAD is not a symbolic ref

然而, git rev-parse refs/heads/master指向我可以恢复的一个很好的提交(在我的情况下,最后一次提交,你可以通过使用git show [SHA]

之后我做了很多杂乱的事情,但似乎已经解决的只是,

git symbolic-ref HEAD refs/heads/master

头部重新连接!


简单地说,Detached HEAD状态意味着你没有签出任何分支的头部(或小费)

通过例子了解

大多数情况下的分支是多个提交的序列,例如: -

提交1: master - > branch_HEAD(123be6a76168aca712aea16076e971c23835f8ca)

提交2: master - > 123be6a76168aca712aea16076e971c23835f8ca - > branch_HEAD(100644a76168aca712aea16076e971c23835f8ca)

正如您在上面看到的提交序列,您的分支指向您的最新提交。 所以在这种情况下,如果您签出提交123be6a76168aca712aea16076e971c23835f8ca,那么您将处于分离头部状态,因为您的分支的HEAD指向100644a76168aca712aea16076e971c23835f8ca,并且技术上您在没有分支的HEAD处签出。因此,您处于分离的HEAD状态

理论解释

在本博客中,其明确声明的Git存储库是一个提交树,每个提交都指向其祖先,每个提交指针都会更新,并且这些指向每个分支的指针都存储在.git / refs子目录中。 标签存储在.git / refs /标签中,分支存储在.git / refs /头中。 如果您查看任何文件,您会发现每个标签对应一个文件,具有40个字符的提交散列,并且如上面@Chris Johnsen和@Yaroslav Nikitenko所解释的那样,您可以查看这些引用


这完美地为我工作:

1. git stash以保存您的本地修改

如果你想放弃更改
git clean -df
git checkout -- .
git clean删除所有未跟踪的文件(警告:虽然它不会删除直接在.gitignore中提到的忽略文件,但它可能会删除文件夹中的忽略文件),并且git checkout将清除所有未经处理的更改。

2. git checkout master切换到主分支(假设你想使用master)
3. git pull从主分支拉最后提交
4. git status为了检查一切看起来不错

On branch master
Your branch is up-to-date with 'origin/master'.

首先,让我们澄清一下HEAD是什么以及它在分离时的含义。

HEAD是当前签出的提交的符号名称。 当HEAD没有分离时(“正常” 1情况:你有一个分支被检出),HEAD实际上指向分支的“ref”,分支指向提交。 HEAD因此“附属于”一个分支。 当您进行新的提交时,HEAD指向的分支会更新为指向新的提交。 由于HEAD指向分支,HEAD会自动跟随。

  • git symbolic-ref HEAD产生refs/heads/master
    名为“主”的分支已检出。
  • git rev-parse refs/heads/master yield 17a02998078923f2d62811326d130de991d1a95a
    该提交是主分支的当前提示或“头”。
  • git rev-parse HEAD也产生17a02998078923f2d62811326d130de991d1a95a
    这就是“符号参考”的含义。 它通过其他参考指向一个对象。
    (符号引用最初是作为符号链接实现的,但后来更改为带有额外解释的纯文本文件,以便可以在没有符号链接的平台上使用它们。)

我们有HEADrefs/heads/master17a02998078923f2d62811326d130de991d1a95a

当HEAD被分离时,它直接指向一个提交 - 而不是通过一个分支间接指向一个提交。 你可以将分离的HEAD想象成一个未命名的分支。

  • git symbolic-ref HEAD失败并fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD得出17a02998078923f2d62811326d130de991d1a95a
    由于它不是符号引用,它必须直接指向提交本身。

我们有HEAD17a02998078923f2d62811326d130de991d1a95a

用分离的HEAD记住的重要事情是,如果它指向的提交不是其他引用(其他引用无法达到它),那么当您签出其他提交时它将变成“悬挂”。 最终,这种悬而未决的提交将通过垃圾收集过程进行修剪(默认情况下,它们会保留至少2周,并且可能会被HEAD的reflog引用而延长)。

1使用分离的HEAD进行“正常”工作是完全正确的,您只需跟踪自己在做什么以避免将丢弃的历史记录从reflog中删除。

交互式底座的中间步骤是通过分离的HEAD完成的(部分是为了避免污染活动分支的引用日志)。 如果您完成了全部的重新布局操作,它将使用重新布局操作的累积结果更新您的原始分支,并将HEAD重新附加到原始分支。 我的猜测是,你从来没有完全完成rebase进程; 这会让你有一个分离的HEAD指向最近由rebase操作处理的提交。

为了从你的情况中恢复,你应该创建一个分支,指向你分离的HEAD当前指向的提交:

git branch temp
git checkout temp

(这两个命令可以缩写为git checkout -b temp

这会将您的HEAD重新附加到新的temp分支。

接下来,您应该将当前提交(及其历史记录)与您希望工作的常规分支进行比较:

git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp

(您可能会想要尝试日志选项:add -p ,leave off --pretty=…以查看整个日志消息等)

如果你的新temp分支看起来不错,你可能想更新(例如) master指向它:

git branch -f master temp
git checkout master

(这两个命令可以缩写为git checkout -B master temp

您可以删除临时分支:

git branch -d temp

最后,你可能会推动重建的历史:

git push origin master

如果远程分支不能被快速转发到新的提交中,你可能需要在这个命令的末尾添加--force ,以便推送(即,你丢弃或重写了一些现有的提交,或者重写了一些历史记录)。

如果您正在进行重建操作,您应该清理它。 您可以通过查找目录.git/rebase-merge/来检查是否正在进行重新.git/rebase-merge/ 。 您可以通过删除该目录(例如,如果您不再记住激活的rebase操作的目的和上下文)来手动清理正在进行的rebase。 通常你会使用git rebase --abort ,但是这会做一些你可能想要避免的额外重置操作(它会将HEAD移回原始分支并将其重置回原始提交,这将撤销我们上面做的一些工作)。





git