git commit之后,已删除的文件重新出现在远程存储库中

时间:2017-05-04 15:18:20

标签: git github

我在GitHub上有一个远程存储库以及一个相应的本地存储库和工作区。

问题就像这样

  1. 我从远程拉出并开始处理文件
  2. 与此同时,我的同事删除了一个文件(Bar.java)并修改了第10行的文件Foo.java并将其更改推送到远程仓库。
  3. 我也对Foo.java的同一行进行了更改
  4. 我提交了我的Foo.java并执行了拉动以查看是否存在任何冲突
  5. 我得到并解决了冲突
  6. 当我尝试将更改添加到索引时,我在暂存中获得了两个文件,一个是预期的Foo.java,另一个是标记为删除的Bar.java。
    1. 如果我从Staging中删除已删除的文件Bar.java并仅提交Foo.java(仅我的更改)并执行推送到上游,则删除的文件将显示在Remote Repo中!

      < / LI>
    2. 如果将两个文件添加到索引中,提交它并向上游执行,则只删除已删除的文件在远程仓库中删除 我假设当我做一个Pull并且存在冲突时会发生这种情况,因此我的Local Repo没有更新,但我的工作区得到了更新。这是正确的吗?

  7. 基于此,我有以下问题:

    • 当我执行拉动时如何在发生冲突时如何使我的本地存储库与远程回购同步?

    • 当我将本地仓库推送到上游时会发生什么?整个远程仓库是否会被覆盖,或者有选择地合并我提交的变更?

2 个答案:

答案 0 :(得分:2)

要完全了解正在发生的事情(或与遥控器同步意味着什么),我们需要记住git中的三种类型的存储区域:工作树,索引,数据库。你在本地拥有这三个,你也关心遥控器上的数据库。

让我们逐步解决有冲突的pull。但是为了使图片更清晰,我们假设我们先做fetch(这很好,因为这是当你要求pull时git执行的第一步。)

首先,你有一个提交为

的本地回购
I --- A <--(master)(origin/master)

您在本地进行一些更改并提交它们。

I --- A <--(origin/master)
       \
        B <--(master)

但与此同时,你的同事推动了对遥控器的更改,所以它有

I --- A --- C <--(master)

当你fetch时,你得到了

I --- A --- C <--(origin/master)
       \
        B <--(master)

此时,您的数据库包含来自遥控器的所有对象,因此您可以说您与遥控器完全同步。但遥控器有点落后于你所拥有的东西;它还不知道B

pull的下一步是将origin/master合并到master。如果存在冲突,则合并将停止,工作树和索引处于“合并”状态。索引包含对没有冲突的文件的更改,并且您的工作树包含有冲突的文件的冲突标记(以及任何非冲突的更改)。

这些更改是相对于您的本地主人(即相对于B)表示的,因为这就是您要合并的内容。所以“删除Bar.java”是一个没有冲突合并到你的本地分支的变化 - 但你仍然可以覆盖它。即使git只有需要来处理此时的冲突,您可以根据需要对提交进行任何更改。允许这是好的和必要的 - 因为有时解决冲突需要在实际冲突线的区域之外进行改变;但在这种情况下,你可能不想这样做。因此,除了add修改文件以解决冲突之外,您应该单独留下索引。

最后你已经解决了冲突和提交,所以你有

I --- A --- C <--(origin/master)
       \     \
        B --- M<--(master)

Noe您已在master上创建了另一个新提交(合并),因此遥控器将落后于push。您可以通过使用--rebase选项来避免此提交;这个过程会类似,但你最终会得到

I --- A --- C <--(origin/master)
             \     
              B' <--(master)

(其中B'B的重新定位替代品。即便如此,origin/master仍然落后于你推动。

有了背景知识,让我们专门解答你的问题:

当我执行拉动时如何在发生冲突时如何使我的本地存储库与远程回购同步?

pull的第一步是fetch,它确实让您完全同步,因为您拥有来自遥控器的所有信息。你仍然有一些信息还没有在遥控器上(你的本地提交),直到你解决了冲突,你应该做的不多。

任何认为您未完全同步的感觉是因为您的工作树和索引反映了pullfetch之后启动的合并进度。 (如果您只完成fetch,则可以立即checkoutorigin/master并且您会看到遥控器上的所有内容。)

当我将本地仓库推送到上游时会发生什么?是否会覆盖整个远程仓库,或者有选择地合并我提交的更改?

push向远程发送更新的ref(以及支持它们的其他对象)。所以在这种情况下,你正在推动master分支的参考:

1)git更新本地存储库中的origin/master ref

2)git确保origin/master的{​​{1}}仍然是“可达的”(通过父提交指针);这意味着,master中的所有更改都已合并到origin/master中,因此根据请求更新遥控器master只会应用您在本地添加的新更改{{1} }}

3)如果(2)看起来不错,那么:

3a)将所需对象发送到远程并添加到其数据库中。在这种情况下,提交mastermaster(或提交B如果您执行了M)和其中包含的对象。

3b)远程B'引用已更新,以匹配您当地的rebase参考

虽然master引用被覆盖,但说回购被覆盖是不正确的。你主要是向它添加数据。如果这看起来有点模糊,那么您添加的数据可以包含撤消先前由其他人完成的更改的指令。在拉动期间正确处理合并步骤将决定是否发生这种情况。

答案 1 :(得分:1)

如果您决定将文件保留在修订版本上(放弃删除),那么它肯定会显示在生成的修订版本上。如果你决定跟进并在索引上保留删除,那么文件就会消失。