如何将分离的 HEAD 与 master/origin 协调起来? [英] How can I reconcile detached HEAD with master/origin?

查看:37
本文介绍了如何将分离的 HEAD 与 master/origin 协调起来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new at the branching complexities of Git. I always work on a single branch and commit changes and then periodically push to my remote origin.

最近的某个地方,我重置了一些文件以让它们退出提交暂存,然后做了一个 rebase -i 以摆脱最近的几个本地提交.现在我处于一种我不太明白的状态.

Somewhere recently, I did a reset of some files to get them out of commit staging, and later did a rebase -i to get rid of a couple recent local commits. Now I'm in a state I don't quite understand.

在我的工作区域中,git log 显示的正是我所期望的——我在正确的火车上,有我不想消失的提交,还有新的提交等等.

In my working area, git log shows exactly what I'd expect-- I'm on the right train with the commits I didn't want gone, and new ones there, etc.

但我只是推送到远程存储库,有什么不同 - 我在 rebase 中杀死的几个提交被推送了,而本地提交的新提交不在那里.

But I just pushed to the remote repository, and what's there is different-- a couple of the commits I'd killed in the rebase got pushed, and the new ones committed locally aren't there.

我认为master/origin"与 HEAD 是分离的,但我不是 100% 清楚这意味着什么,如何使用命令行工具对其进行可视化,以及如何修复它.

I think "master/origin" is detached from HEAD, but I'm not 100% clear on what that means, how to visualize it with the command line tools, and how to fix it.

推荐答案

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

First, let’s clarify what HEAD is and what it means when it is detached.

HEAD 是当前签出提交的符号名称.当 HEAD 没有分离时(正常"1 情况:你有一个分支被检出),HEAD 实际上指向一个分支的ref",而分支指向提交.HEAD 因此附加"到一个分支.当您进行新提交时, HEAD 指向的分支将更新为指向新提交.HEAD 会自动跟随,因为它只是指向分支.

HEAD is the symbolic name for the currently checked out commit. When HEAD is not detached (the "normal"1 situation: you have a branch checked out), HEAD actually points to a branch’s "ref" and the branch points to the commit. HEAD is thus "attached" to a branch. When you make a new commit, the branch that HEAD points to is updated to point to the new commit. HEAD follows automatically since it just points to the branch.

  • git symbols-ref HEAD 产生 refs/heads/master
    名为master"的分支被检出.
  • git rev-parse refs/heads/master yield 17a02998078923f2d62811326d130de991d1a95a
    该提交是主分支的当前提示或头".
  • git rev-parse HEAD 也产生 17a02998078923f2d62811326d130de991d1a95a
    这就是符号引用"的含义.它通过其他一些引用指向一个对象.
    (符号引用最初是作为符号链接实现的,但后来改为带有额外解释的纯文件,以便它们可以在没有符号链接的平台上使用.)
  • git symbolic-ref HEAD yields refs/heads/master
    The branch named "master" is checked out.
  • git rev-parse refs/heads/master yield 17a02998078923f2d62811326d130de991d1a95a
    That commit is the current tip or "head" of the master branch.
  • git rev-parse HEAD also yields 17a02998078923f2d62811326d130de991d1a95a
    This is what it means to be a "symbolic ref". It points to an object through some other reference.
    (Symbolic refs were originally implemented as symbolic links, but later changed to plain files with extra interpretation so that they could be used on platforms that do not have symlinks.)

我们有 HEADrefs/heads/master17a02998078923f2d62811326d130de991d1a95a

当 HEAD 被分离时,它直接指向一个提交——而不是通过一个分支间接指向一个提交.您可以将分离的 HEAD 视为位于未命名的分支上.

When HEAD is detached, it points directly to a commit—instead of indirectly pointing to one through a branch. You can think of a detached HEAD as being on an unnamed branch.

  • git Symbolic-ref HEAD 失败并显示 fatal: ref HEAD is not asymbolic ref
  • git rev-parse HEAD 产生 17a02998078923f2d62811326d130de991d1a95a
    由于它不是符号引用,因此它必须直接指向提交本身.
  • git symbolic-ref HEAD fails with fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD yields 17a02998078923f2d62811326d130de991d1a95a
    Since it is not a symbolic ref, it must point directly to the commit itself.

我们有 HEAD17a02998078923f2d62811326d130de991d1a95a

使用分离的 HEAD 需要记住的重要一点是,如果它指向的提交没有被引用(没有其他 ref 可以访问它),那么当您检出其他提交时它将成为悬空".最终,这些悬空提交将通过垃圾收集过程进行修剪(默认情况下,它们至少保留 2 周,并可能通过 HEAD 的 reflog 引用而保留更长时间).

The important thing to remember with a detached HEAD is that if the commit it points to is otherwise unreferenced (no other ref can reach it), then it will become "dangling" when you checkout some other commit. Eventually, such dangling commits will be pruned through the garbage collection process (by default, they are kept for at least 2 weeks and may be kept longer by being referenced by HEAD’s reflog).

1用一个独立的 HEAD 做正常"的工作是完全没问题的,你只需要跟踪你在做什么,以避免不得不从 reflog 中获取丢弃的历史记录.

1 It is perfectly fine to do "normal" work with a detached HEAD, you just have to keep track of what you are doing to avoid having to fish dropped history out of the reflog.

交互式 rebase 的中间步骤是通过分离的 HEAD 完成的(部分是为了避免污染活动分支的 reflog).如果您完成完整的 rebase 操作,它将使用 rebase 操作的累积结果更新您的原始分支,并将 HEAD 重新附加到原始分支.我的猜测是你从未完全完成 rebase 过程;这将为您留下一个分离的 HEAD,指向最近由 rebase 操作处理的提交.

The intermediate steps of an interactive rebase are done with a detached HEAD (partially to avoid polluting the active branch’s reflog). If you finish the full rebase operation, it will update your original branch with the cumulative result of the rebase operation and reattach HEAD to the original branch. My guess is that you never fully completed the rebase process; this will leave you with a detached HEAD pointing to the commit that was most recently processed by the rebase operation.

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

To recover from your situation, you should create a branch that points to the commit currently pointed to by your detached HEAD:

git branch temp
git checkout temp

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

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

This will reattach your HEAD to the new temp branch.

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

Next, you should compare the current commit (and its history) with the normal branch on which you expected to be working:

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

(您可能想尝试使用日志选项:添加 -p,去掉 --pretty=... 以查看整个日志消息等)

(You will probably want to experiment with the log options: add -p, leave off --pretty=… to see the whole log message, etc.)

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

If your new temp branch looks good, you may want to update (e.g.) master to point to it:

git branch -f master temp
git checkout master

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

然后可以删除临时分支:

You can then delete the temporary branch:

git branch -d temp

最后,您可能想要推送重建的历史记录:

Finally, you will probably want to push the reestablished history:

git push origin master

如果远程分支无法快进"到新提交(即您删除或重写了一些现有提交,或以其他方式重写一些历史记录).

You may need to add --force to the end of this command to push if the remote branch can not be "fast-forwarded" to the new commit (i.e. you dropped, or rewrote some existing commit, or otherwise rewrote some bit of history).

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

If you were in the middle of a rebase operation you should probably clean it up. You can check whether a rebase was in process by looking for the directory .git/rebase-merge/. You can manually clean up the in-progress rebase by just deleting that directory (e.g. if you no longer remember the purpose and context of the active rebase operation). Usually you would use git rebase --abort, but that does some extra resetting that you probably want to avoid (it moves HEAD back to the original branch and resets it back to the original commit, which will undo some of the work we did above).

这篇关于如何将分离的 HEAD 与 master/origin 协调起来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆