我本地仓库有3-4个分支,当我在其中一个分支上工作时,我所做的更改会传播到其他分支。事实上,如果我git reset --hard origin
其中一个分支,它将重置每个本地分支。
我应该如何只保留更改在一个分支中?
请注意,我对git不熟悉。
我本地仓库有3-4个分支,当我在其中一个分支上工作时,我所做的更改会传播到其他分支。事实上,如果我git reset --hard origin
其中一个分支,它将重置每个本地分支。
我应该如何只保留更改在一个分支中?
请注意,我对git不熟悉。
在Git中进行新提交是有技巧的。其他版本控制系统要简单得多,因为在这些系统中,您的工作区也是您建议的下一个提交。但在Git中并非如此!Git添加了一件更重要的事情,即使您不想知道,也必须了解它。这个东西非常重要,尽管您看不到,Git称之为“索引”、“暂存区”,有时候-现在很少了-称之为“缓存”。所有三个名称都可以指同一件事情。它以不同的方式使用(“缓存”术语现在主要用于内部数据结构,这就是为什么现在它有点罕见),但对索引的相当不错的简短描述是,它保存您的“下一个建议提交”。您可以将其视为保存每个文件副本从当前提交中获取。1
当您更改工作区中的文件时,“索引”中的副本不会发生任何变化。它仍然与您选择的提交中的副本匹配。您必须运行“git add”将文件从工作区复制到索引中。现在,索引副本不再与提交副本匹配,因此您建议下一个提交与当前提交不同。
运行git commit
会从索引中构建一个新的提交,该索引包含当前状态。所以在Git中,你可以在工作树中进行操作,然后使用git add
将更新的文件复制回索引,然后使用git commit
从索引创建新的提交。这有点麻烦,这就是为什么其他系统没有索引的原因:它们不需要让你更新所有文件的中间副本。但是Git有,最好熟悉并了解它。虽然有一些技巧可以尝试隐藏它,2但最终它们会失败:Git中的某些功能只能通过指向索引来解释。
从索引创建了一个新提交后,该新提交成为当前提交。现在当前提交和索引匹配。这也是在git checkout
之后正常情况下:当前提交和索引通常匹配。请参见下文的例外情况。
1从技术上讲,索引保存了对内部Git blob对象的{{引用}}。然而,将文件的索引“复制”视为真正的独立副本,在大多数情况下都可以正常工作——只有当您开始涉及Git内部机制时,您才需要了解blob对象。
2例如,您可以使用git commit -a
代替git commit
。这只是为您运行git add -u
。 add -u
步骤告诉Git:对于所有已经在索引中的文件,请检查它们是否需要执行git add
。如果是,则立即执行。然后提交使用已更新的索引。这里还有一些其他的复杂性,但仅当提交步骤本身失败时才会出现。但是,只有了解索引,才能在这些情况下正确地解释它们。
当你git checkout
某个特定的提交(通过某个特定的分支名称找到)时,Git将从该提交中填充你的索引和工作树。这可能会更新一些文件-无论是在索引还是工作树中-并且如果它们在旧提交和新提交中相同,则不会更改其他文件。
但是,如果您对索引和/或工作树进行了某些更改并且没有提交,Git将尝试在可能的情况下保留该修改。这就是您看到的情况。在这种情况下,您当前的提交和索引不匹配。(在某些情况下,工作树中发生的情况甚至更加复杂。有关此问题的过多信息,请参见Checkout another branch when there are uncommitted changes on the current branch。)
在Git中,每个提交都具有唯一的哈希ID。这个哈希ID是由字母和数字组成的一串很长的丑陋字符串。从技术上讲,它是提交内容的SHA校验和的十六进制表示;但是它的主要特点是,每个 Git都将同意此提交获取此哈希ID,并且没有其他提交可以具有该哈希ID。每个其他提交都有一些其他哈希ID。
哈希ID看起来随机,对人类来说很难记住。计算机可以为我们记住它们。这就是分支名称的真正含义。... <-F <-G <-H <--master
A--B--C--D--E--F--G--H <-- master
代表一个具有八个提交的Git仓库,每个提交都有自己独特的哈希ID和一个分支名name,master
。
我们可以像这样添加另一个分支名,也指向提交H
:
git branch develop
git checkout develop
HEAD
附加到两个分支名称中的一个:...--F--G--H <-- master, develop (HEAD)
...--F--G--H <-- master, develop (HEAD)
\
I
< p > git commit
的最后一步是棘手的部分:Git 现在将 I
的哈希 ID 写入与 HEAD
相附的名称中。 在这种情况下,那就是 develop
:
...--F--G--H <-- master
\
I <-- develop (HEAD)
develop
指向提交 I
。之前在 develop
上的提交直到 H
仍然存在于 develop
上。不过,名称 develop
特别选择了提交 I
。Git 现在可以从 I
开始向后工作,找到 H
,然后是 G
,再然后是 F
,以此类推;或者可以从 master
开始查找 H
,然后向后查找找到 G
,再然后是 F
,以此类推。git fetch
和 git push
)涉及连接两个Git,并让它们找出它们共享哪些提交,以及发送者将要发送哪些提交。接收方最终必须在某处保存最后一个哈希ID,以便稍后可以再次找到这些提交,但我们还没有介绍这是如何工作的。git status
可以比较其中的内容,并告诉您这些信息。您的工作树是您可以查看和处理文件的地方。您必须将它们复制回索引/暂存区,以便创建保存更新后文件快照的新提交。在执行此操作之前,您所做的一切都只是更改文件的工作树副本。