代码之家  ›  专栏  ›  技术社区  ›  OliverRadini

重新设置为远程,缺少更改;发生了什么事?

git
  •  1
  • OliverRadini  · 技术社区  · 7 年前

    我今天遇到了一个问题,我仍然不知道发生了什么。

    dev 为方便起见:

    a --- b --- c --- e <-- local/dev
    
    a --- b --- c --- d <-- remote/dev
    

    我认为这样做的方法是:

    git fetch
    git checkout dev
    git rebase remote/dev
    

    我很肯定我过去也做过。我预期的结果是:

    a --- b --- c --- d --- e
    

    提交消息似乎表明这确实是历史的状态, 中包含的更改 e 他们已经不在了

    可能是我没有按照上面概述的步骤进行操作,也可能是因为必须有其他因素来解释所发生的事情。我想我的问题是, 发生的事情是否超出正常范围,或者必须有其他情况来解释?

    也许是 git pull --rebase 这是更好的选择。

    1 回复  |  直到 7 年前
        1
  •  2
  •   torek    7 年前

    一定还有其他情况(我不知道它们可能是什么。)

    也许是 git pull --rebase

    这也是同样的道理。您的原始命令序列是 git checkout dev 加上命令对 git fetch; git rebase . 什么 git pull 这是跑步吗 git fetch 然后是第二个Git命令,通常是 git merge git-pull——重基 git rebase 第二因此:

    git checkout dev; git pull --rebase
    

    同:

    git checkout dev; git fetch; git rebase
    

    它只短了四个字符(包括分号和空格)。

    请注意,原始提交仍然可以在存储库中使用。要找到它们,请使用以下两种机制之一:

    • ORIG_HEAD :这是一个在进行任何更改之前设置多个不同命令的标记。如果你做的最后一件改变是 吉特重基 将是在进行更改之前保存的任何重基(设置它的其他命令是 git am , git reset 合并分支 ,当它执行快进操作而不是执行合并时。)

    • 这个 重新记录 对于 HEAD . 每一个都有编号和时间戳。旧条目最终会过期:Git确保在默认情况下至少30或90天之前不会发生这种情况。在没有其他非常有用的背景信息的情况下,解释这里发生的事情有点棘手。

      (有关背景信息,请参见 Think Like (a) Git . 到底是怎么回事 reflog entriesreachable来自引用的当前值,默认情况下,该值为90天到期,而 refs/stash

    除了事实上只有一个 ,并且reflog条目将根据 而不是被存储到中的下一个值覆盖 原头 ,这两件事的工作方式几乎相同。

    原头 ,使用 git log ORIG_HEAD git reflog show git log -g ( 实际调用 git日志-g git log 选择 git reflog ).

    让我们看一看由于某些原因出现错误的重新基准,最典型的是,需要修复太多合并冲突的重新基准。我们将从启动它的命令序列开始,但要明确地拼写如下:

    git checkout dev && git fetch && git rebase
    

    这个 git签出开发 git获取 步骤填写 origin/dev ,以及 吉特重基 dev 那不在我们的范围之内 起源/发展 . 这个 &&

    副本将放在提交之后 要点。就是以后, git获取 ,我们的存储库中可能有以下提交图:

    ...--o--o--A--B--C   <-- dev (HEAD)
             \
              E--F   <-- origin/dev
    

    我们想要的结果是:

    ...--o--o--A--B--C   [abandoned]
             \
              E--F   <-- origin/dev
                  \
                   A'-B'-C'  <-- dev (HEAD)
    

    哪里 A' 这是我们的 A , B' 这是我们的 B ,及 C' 这是我们的 C

    如果一切正常,或者至少,如果 一切都很好——再基础以以下内容结束:

    ...--o--o--A--B--C   <-- ORIG_HEAD, dev@{1}
             \
              E--F   <-- origin/dev
                  \
                   A'-B'-C'  <-- dev
    

    这个 原头 设置在重基完成后完成。这个 dev@{1} 是的reflog条目 再底座完成后(请注意,与我们执行其他命令一样,entry#1被下推到entry#2、#3,依此类推,因此您必须使用 git reflog秀 现在 如果不是在完成之后。)

    如果你已经完成了重基,然后运行 吉特日志 或者查看结果,或者运行测试,或者其他什么,如果您感到恐惧,想要恢复,您现在可以运行:

    git reset --hard ORIG_HEAD
    

    或:

    git reset --hard dev@{1}
    

    这两项都将:

    • 找到指定的提交,它是提交的实际哈希值 C ;
    • 发展 指向此提交(在流程中向下推一个reflog条目);和
    • --hard )因此,索引树和工作树现在匹配提交 .

    注意 将使 原头 点在哪里

    ...--o--o--A--B--C   <-- dev (HEAD), dev@{2}
             \
              E--F   <-- origin/dev
                  \
                   A'-B'-C'  <-- ORIG_HEAD, dev@{1}
    

    平原 ,从 并向后工作,现在将显示我们的承诺 那么 那么 A. ,然后是最右边的 o

    另一方面,假设我们 开始 重新设置基础,并已达到这一点:

    ...--o--o--A--B--C   <-- dev
             \
              E--F   <-- origin/dev
                  \
                   A'-B'  <-- HEAD
    

    我们正处于重新调整的中期,试图选择承诺。 C C' ,并发生了一系列冲突。我们审视冲突并决定: 毕竟,现在不是这样做的时候。 我们想回到我们开始之前的情况。

    git status 命令将告诉我们,我们处于“分离头”模式,在重新基地的中间。我们经营:

    git rebase --abort
    

    这将停止我们的再基地和重新检查 发展

    ...--o--o--A--B--C   <-- dev (HEAD)
             \
              E--F   <-- origin/dev
                  \
                   A'  <-- HEAD@{2}
                    \
                     B'  <-- HEAD@{1}
    

    这一次,我画的是 重新记录记住提交的条目 A' . 这些总是存在的,因为reflog条目通常是不可见的,所以大多数时候我们只是将它们从图形图形中排除。这对我们来说是正确的 还有:当我们不在乎它的时候,我们就忽略它,因为 除非我们明确要求,否则不要看它。

    另一个例子

    git rebase --quit 一个相对较新的选择,或者实际上仍然处于中间,存在冲突。在这种情况下,你应该 首轮 git状态

    git status
    

    如果这说明你处于ReBASE的中间,你可以选择完成ReBASE或中止它,如上面的例子。

    git reflog 找到任何成功的部分樱桃,并制作一个指向此的新临时分支。例如,假设我们成功地 B' C' ,并意外地用 git rebase --abort . 我们投入了大量工作来解决与客户的冲突 A' 并且想要他们回来。现在我们运行:

    git reflog
    

    HEAD@{1} , HEAD@{2}

    …--o--o--A--B--C<--发展主任
    \
    E--F<--起源/发展
    \
    

    B' 是有价值的,让我们给它一个新的分支名称,例如。, new-dev :

    git checkout -b new-dev HEAD@{1}
    

    现在我们有了这个图,我们将在没有 HEAD@{...} 部分:

    ...--o--o--A--B--C   <-- dev
             \
              E--F   <-- origin/dev
                  \
                   A'-B'  <-- new-dev (HEAD)
    

    发展 指向提交 C' 或者无论我们选择什么;但现在,我们可以继续努力了 保持 发展 围绕

    要记住的要点

    • 提交通常是永久的,并且完全不可更改。它们的真名是它们丑陋的大哈希ID,但人类无法记住和处理它们,所以我们给它们取了名字。只要他们还在,他们就会一直呆着 可达成的 (见 ).

    • 分支机构 名字 是保存哈希ID的人类可读标识符。 选择名字; 吉特 选择它们的值(基础提交的哈希ID)。每当我们进行更改时,当前分支名称的值将自动更新 承诺。每个名字都指向 最后的 提交Git在我们 分支机构,以及 承诺Git应该 退房 当我们 git checkout

    • git签出 使用分支名称附加名称 到其中一个分支名称,以便新提交将更新该分支名称。使用 具有提交哈希ID,或名称不是分支名称, 分离 ,使其直接指向某个提交。

    • 使用 git重置 现在的 指向的分支 任何 (即名称) git rebase --continue git rebase --skip 此时可能会删除大量提交。

    • 原头 就像是一个廉价的(在所有意义上)版本的回流:它记得 很多

    • 真正的倒影是给你的 每个分支加一个名称保存 许多的 git reflog秀 git日志-g .

    • 吉特重基 作品作者:

      1. 分离头部,使其指向提交,然后复制。
      2. 1. 要复制的每个提交,一次一个。每个樱桃采摘可能有冲突;如果是这样,Git将停止并让您解决冲突。
      3. 在最后一次樱桃采摘结束后, 和设置
    • 吉特拉力 不做任何特别的事。这是一条方便的捷径。我建议你避免这样做,但如果你真的确定要跑步的话 吉特重基 刚过一个星期 git获取 git获取


    1. git rebase --interactive 字面上运行 git cherry-pick ; 在现代Git中,两者都内置在Git内部称为 测序器 . 其他一些重基模式也确实使用cherry pick。非交互式重基的默认路径实际上是不同的路径,使用 git format-patch 吉特阿姆 复制提交。从某种意义上说,该路径有点缺陷,因为它不像基于cherry-pick的方法那样处理重命名。