为什么在压缩后错误切换分支?没有什么可承诺的
Why error switching branches after squashing? Nothing to commit
我只是压缩了我的远程提交,然后将它们强制推送到远程。 git status
表示没有变化。为什么我在尝试签出开发分支时会收到此错误?
error: Your local changes to the following files would be overwritten
by checkout:
[file here]
Please commit your changes or stash them before you switch branches.
Aborting
这是完成的事情:
git rebase -i origin/feature/EX-1576~14 feature/EX-1576
git push --force origin feature/EX-1576
而 git status
什么也没显示:
$ git status
On branch feature/EX-1576
Your branch is up to date with 'origin/feature/EX-1576'.
nothing to commit, working tree clean
据我了解,当您进行本地更改时会出现此错误,但我没有进行本地更改。我只是想这样做:
git checkout develop
TL;DR
遵循 Git 的建议:对于它命名的每个文件,将该文件移动到其他地方(让开,可能完全从项目中移出),或提交它。然后进行结帐,查看替换了这些文件的文件,并决定是保留替换文件,还是使用结帐前保存的副本。
小心 git update-index --assume-unchanged
或 git update-index --skip-worktree
:它们在某些情况下效果很好,但会让您落入这个特定的陷阱。
由于您在 Windows,默认情况下会将名为(例如)readme
的文件与其他名为 README
的不同文件合并 - Windows 无法同时存储两者;它只会破坏其中一个——小心区分大小写的文件名,通常由一些 Linux 程序员创建。 :-)
长
It's my understanding that the error occurs when you have local changes ...
这不太对。当操作(在本例中为 git checkout
)将覆盖某些 state.
时,您会收到该错误
Git 根本不是 变化 。 Git 主要是关于 commits,并提交保存 state——你所有文件的快照,以及你的元数据:你的名字和电子邮件地址,你提交的时间,以及关于你为什么提交的日志消息,例如。 (此元数据中包含另一个关键项,即父提交哈希 ID,但对于这个特定问题,我们可以忽略它。)
状态和变化之间的区别就像谈论天气:说今天比昨天暖和告诉你关于温度的一件事,但不是全部。说昨天是 15˚C (59˚F),今天是 20 / 68,告诉你关于温度的一切。 (嗯,关于这个温度,无论如何。)请注意,需要两个 状态 才能得出 变化: 我们必须减去昨天的温度从今天开始,看看它可能会暖和或冷多少。
无论如何,提交存储状态:提交的每个文件的完整副本,截至提交时。此副本实际上来自 Git 的 index,但我们暂时忽略了这一细微差别。不过,它马上就会出现。所以每次提交都非常独立于其他所有提交。
你的 work-tree,另一方面,不是 Git 保存的东西(根本,真的,因为索引)。你用它来处理你的文件,因为提交的副本是一种特殊的、冻结的、压缩的(有时压缩得很厉害),仅 Git-only 格式。为了使这些有用,Git 需要将它们扩展为普通格式的文件,您可以使用,如果您愿意,可以 更改 。那些扩展的副本进入你的工作树。
现在,关于工作树的一个问题是它允许包含您不会提交的文件。这些是 Git 称为 未跟踪的 文件。通常,如果您的工作树中有一个文件未被跟踪——不会被提交——Git 将抱怨 那个文件。您可以通过在 .gitignore
中列出未跟踪的文件来让 Git 闭嘴,但这比看起来更棘手。这就是 Git 再次用索引的存在打你的脸。
索引是一个奇怪而美妙但也令人讨厌的东西,它几乎是 Git 所独有的。在以冻结 Git-only 压缩形式存储文件的提交和允许您处理文件的工作树之间,Git 放置了 third 每个文件的副本。每个文件的索引副本都是特殊的 Git-only 格式,但不是被冻结,而是 准备 冻结:如果你愿意的话,有点糊涂。关键是您可以 更改 这个副本,这就是 git add
所做的:它将文件从工作树复制到索引中。
实际上是索引副本的存在决定了文件是否被跟踪。如果文件在索引中,则它被跟踪;如果不是,则未跟踪。在 .gitignore
中列出文件意味着:如果它不在索引中,并且在工作树中,请不要抱怨。 但它有第二个副作用,即是:在某些情况下,它授予 Git 销毁 文件的权限。
文件名大小写问题
Linux 程序员愉快地编写并提交了两个不同的文件,一个名为 README
,另一个名为 readme
或 Readme
。或者他们对头文件做同样的事情:ip.h
和 IP.h
(在旧的 Linux 内核树中)。当使用 Mac 或 Windows 框的人尝试处理这些提交时,他们会被这些系统上的 work-tree 不能'将两个文件都放在适当的位置。 (Git的索引处理得很好,因为索引实际上是一个文件,.git/index
。)
如果您正在从一个文件名为 README
的提交切换到一个文件名为 Readme
的提交,或者两者都有,Git 有时会因此而变得有点混乱,不知道该怎么办。 (Git 总有一天需要对此更加聪明。)
假设不变并跳过工作树
无论如何,假设索引中有一个文件。如果您更改工作树副本,Git 会告诉您您有一个修改过的跟踪文件。如果你不想Git一直提醒你这个,你可以用git update-index --assume-unchanged
或git update-index --skip-worktree
专门标记那个文件。
当你这样做时——我想你可能做过——Git 停止比较文件的索引副本与工作树副本,因为git status
命令,并且不会将文件的工作树副本复制到索引副本之上,用于 git add
命令。这意味着您可以获取一个配置文件,出于某种原因对其进行修改,但仍然有 new 提交——使用文件的 index 副本—存储文件的原始版本,即在设置假定不变或跳过工作树位之前从提交中进入工作树的版本。
但是git checkout
必须,当它切换到其他提交时,用提交中的(不同的)提交副本替换该文件的索引副本你要切换到。发生这种情况时,Git 不仅会更新索引副本,还会覆盖工作树副本。因此,如果您有一个标有这两个位中的任何一个的文件,则在使用 git checkout
.
时可能会出现该错误
这是个问题吗?也许是,也许不是。如果你强制 git checkout
检查另一个提交,Git 将用另一个提交的文件覆盖索引条目,并用另一个提交的文件替换该文件的工作树副本.由您决定这是否可行,如果不行,您是否需要先将文件移开,或者清除这些位并继续添加并提交文件。
也有文件被半忽略的极端情况
另一方面,假设您没有使用git update-index
设置那些索引位。您仍然可以有一个普通的、未跟踪的文件,甚至可能在 .gitignore
中列出一个以保持 Git 安静。但是一些 other 提交可能有相同文件的(不同版本),如果你有 Git 切换到 that 提交, Git 将不得不 replace 您未跟踪的工作树文件,其中它是 tracked 文件的提交版本。
在这种情况下,git checkout
有时(但不总是)也会抱怨。通常它会说结帐会覆盖 untracked 文件。如果文件在 .gitignore
中列出,这将允许 Git 的某些部分破坏它。幸运的是 git checkout
通常对这些事情非常小心。
我只是压缩了我的远程提交,然后将它们强制推送到远程。 git status
表示没有变化。为什么我在尝试签出开发分支时会收到此错误?
error: Your local changes to the following files would be overwritten by checkout:
[file here]
Please commit your changes or stash them before you switch branches.
Aborting
这是完成的事情:
git rebase -i origin/feature/EX-1576~14 feature/EX-1576
git push --force origin feature/EX-1576
而 git status
什么也没显示:
$ git status
On branch feature/EX-1576
Your branch is up to date with 'origin/feature/EX-1576'.
nothing to commit, working tree clean
据我了解,当您进行本地更改时会出现此错误,但我没有进行本地更改。我只是想这样做:
git checkout develop
TL;DR
遵循 Git 的建议:对于它命名的每个文件,将该文件移动到其他地方(让开,可能完全从项目中移出),或提交它。然后进行结帐,查看替换了这些文件的文件,并决定是保留替换文件,还是使用结帐前保存的副本。
小心 git update-index --assume-unchanged
或 git update-index --skip-worktree
:它们在某些情况下效果很好,但会让您落入这个特定的陷阱。
由于您在 Windows,默认情况下会将名为(例如)readme
的文件与其他名为 README
的不同文件合并 - Windows 无法同时存储两者;它只会破坏其中一个——小心区分大小写的文件名,通常由一些 Linux 程序员创建。 :-)
长
It's my understanding that the error occurs when you have local changes ...
这不太对。当操作(在本例中为 git checkout
)将覆盖某些 state.
Git 根本不是 变化 。 Git 主要是关于 commits,并提交保存 state——你所有文件的快照,以及你的元数据:你的名字和电子邮件地址,你提交的时间,以及关于你为什么提交的日志消息,例如。 (此元数据中包含另一个关键项,即父提交哈希 ID,但对于这个特定问题,我们可以忽略它。)
状态和变化之间的区别就像谈论天气:说今天比昨天暖和告诉你关于温度的一件事,但不是全部。说昨天是 15˚C (59˚F),今天是 20 / 68,告诉你关于温度的一切。 (嗯,关于这个温度,无论如何。)请注意,需要两个 状态 才能得出 变化: 我们必须减去昨天的温度从今天开始,看看它可能会暖和或冷多少。
无论如何,提交存储状态:提交的每个文件的完整副本,截至提交时。此副本实际上来自 Git 的 index,但我们暂时忽略了这一细微差别。不过,它马上就会出现。所以每次提交都非常独立于其他所有提交。
你的 work-tree,另一方面,不是 Git 保存的东西(根本,真的,因为索引)。你用它来处理你的文件,因为提交的副本是一种特殊的、冻结的、压缩的(有时压缩得很厉害),仅 Git-only 格式。为了使这些有用,Git 需要将它们扩展为普通格式的文件,您可以使用,如果您愿意,可以 更改 。那些扩展的副本进入你的工作树。
现在,关于工作树的一个问题是它允许包含您不会提交的文件。这些是 Git 称为 未跟踪的 文件。通常,如果您的工作树中有一个文件未被跟踪——不会被提交——Git 将抱怨 那个文件。您可以通过在 .gitignore
中列出未跟踪的文件来让 Git 闭嘴,但这比看起来更棘手。这就是 Git 再次用索引的存在打你的脸。
索引是一个奇怪而美妙但也令人讨厌的东西,它几乎是 Git 所独有的。在以冻结 Git-only 压缩形式存储文件的提交和允许您处理文件的工作树之间,Git 放置了 third 每个文件的副本。每个文件的索引副本都是特殊的 Git-only 格式,但不是被冻结,而是 准备 冻结:如果你愿意的话,有点糊涂。关键是您可以 更改 这个副本,这就是 git add
所做的:它将文件从工作树复制到索引中。
实际上是索引副本的存在决定了文件是否被跟踪。如果文件在索引中,则它被跟踪;如果不是,则未跟踪。在 .gitignore
中列出文件意味着:如果它不在索引中,并且在工作树中,请不要抱怨。 但它有第二个副作用,即是:在某些情况下,它授予 Git 销毁 文件的权限。
文件名大小写问题
Linux 程序员愉快地编写并提交了两个不同的文件,一个名为 README
,另一个名为 readme
或 Readme
。或者他们对头文件做同样的事情:ip.h
和 IP.h
(在旧的 Linux 内核树中)。当使用 Mac 或 Windows 框的人尝试处理这些提交时,他们会被这些系统上的 work-tree 不能'将两个文件都放在适当的位置。 (Git的索引处理得很好,因为索引实际上是一个文件,.git/index
。)
如果您正在从一个文件名为 README
的提交切换到一个文件名为 Readme
的提交,或者两者都有,Git 有时会因此而变得有点混乱,不知道该怎么办。 (Git 总有一天需要对此更加聪明。)
假设不变并跳过工作树
无论如何,假设索引中有一个文件。如果您更改工作树副本,Git 会告诉您您有一个修改过的跟踪文件。如果你不想Git一直提醒你这个,你可以用git update-index --assume-unchanged
或git update-index --skip-worktree
专门标记那个文件。
当你这样做时——我想你可能做过——Git 停止比较文件的索引副本与工作树副本,因为git status
命令,并且不会将文件的工作树副本复制到索引副本之上,用于 git add
命令。这意味着您可以获取一个配置文件,出于某种原因对其进行修改,但仍然有 new 提交——使用文件的 index 副本—存储文件的原始版本,即在设置假定不变或跳过工作树位之前从提交中进入工作树的版本。
但是git checkout
必须,当它切换到其他提交时,用提交中的(不同的)提交副本替换该文件的索引副本你要切换到。发生这种情况时,Git 不仅会更新索引副本,还会覆盖工作树副本。因此,如果您有一个标有这两个位中的任何一个的文件,则在使用 git checkout
.
这是个问题吗?也许是,也许不是。如果你强制 git checkout
检查另一个提交,Git 将用另一个提交的文件覆盖索引条目,并用另一个提交的文件替换该文件的工作树副本.由您决定这是否可行,如果不行,您是否需要先将文件移开,或者清除这些位并继续添加并提交文件。
也有文件被半忽略的极端情况
另一方面,假设您没有使用git update-index
设置那些索引位。您仍然可以有一个普通的、未跟踪的文件,甚至可能在 .gitignore
中列出一个以保持 Git 安静。但是一些 other 提交可能有相同文件的(不同版本),如果你有 Git 切换到 that 提交, Git 将不得不 replace 您未跟踪的工作树文件,其中它是 tracked 文件的提交版本。
在这种情况下,git checkout
有时(但不总是)也会抱怨。通常它会说结帐会覆盖 untracked 文件。如果文件在 .gitignore
中列出,这将允许 Git 的某些部分破坏它。幸运的是 git checkout
通常对这些事情非常小心。