当前分支:20220620_142027_1
,有一个名为pages/Auth
的目录。
尝试使用git rebase master
命令重新设置master
分支的基础,得到错误:
error: The following untracked working tree files would be overwritten by checkout:
client/modules/activity/pages/auth/components/ActivityForm/index.tsx
client/modules/activity/pages/auth/components/CampaignProductForm/index.tsx
client/modules/activity/pages/auth/components/ChannelForm/index.tsx
Please move or remove them before you switch branches.
Aborting
fatal: Could not detach HEAD
目录名pages/Auth
在master
分支上是小写的,它是pages/auth
。另一个功能分支20220621_142346_1
将所有目录名从大写修改为小写,并将它们合并到master
分支中。
我希望具有小写名称的目录应用于当前分支20220620_142027_1
,覆盖它们。我读过很多类似的问题(Q1),但没有找到明确的解决方案。我该如何解决这个问题?谢谢
无论它如何表现,这里的问题总是一样的。随时间变化的是最短正确解决方案。
让我们尽可能清楚地说明这个问题,因为Git可以存储名为This/File
和this/file
的文件,但有些操作系统不能。问题是这样的:
- 提交是每个文件的完整快照(加上元数据,但我们在这里关注的是快照)
- 从一个提交切换到另一个提交(例如,从一个分支切换到另个分支,或使用
git switch --detach
或git checkout --detach
)需要删除和/或替换工作树中的一些文件,在这些文件中,您可以在提交之间执行实际工作。这就是git rebase
要做的:git switch --detach master
- 一些文件被跟踪,意思是";现在在Git的索引中">
- 一些文件未被跟踪,意思是";现在不在Git的索引中">
假设要被删除的某个文件——无论它是否会被其他具有相同名称的文件取代,都被命名为path/to/file
。
- 如果该文件被跟踪而未被修改,则该文件的内容将安全存储在当前提交中。删除文件是安全的
- 如果该文件被跟踪但被修改,则该文件的内容不会被安全存储在当前提交中。删除此文件是不安全的,您通常会收到一个错误,称此跟踪的文件有您应该提交或以其他方式保存的更改
- 如果该文件未被跟踪,则该文件的内容不会安全存储在当前提交中。删除此文件是不安全的,您通常会收到上面看到的错误消息
(注意:这实际上并没有涵盖所有可能的情况,因为文件可以在当前提交中,但使用git rm
从索引中删除,但由于它是使用git rm --cached
创建或删除的,所以存在于工作树中。我将忽略这种特殊情况:它不会真正影响任何情况。)
在不区分大小写的文件系统(通常在Windows和macOS上找到)上,这适用于名为path/TO/file
、Path/to/file
或path/to/FILE
或其他文件,而不考虑要删除的文件的大小写。因此,对于将创建的新文件,如果该文件只有大小写差异,则该文件实际上将被删除。注意,我们在这里所做的只是添加一个条件:
-
如果当前提交缺少文件
path/to/file
(大写和小写的任意组合)并且新提交具有文件PATH/TO/FILE
(有些情况与下一个"one_answers"不匹配)并且您当前具有path/to/file
(有些情况不匹配),我们认为path/to/file
将被删除。在区分大小写的文件系统中,未跟踪的
path/to/file
不会通过创建PATH/TO/FILE
或path/to/FILE
来删除,因此我们不会将其添加到我们的问题案例中。
考虑到这个问题,一般的解决方案是显而易见的
Git抱怨特定的文件,因为Git知道它将销毁它们的内容,而Git在当前提交中没有保存这些内容。因此,解决方案是明确的:如果内容有价值,则必须保存这些内容。
就是这样!这就是全部答案——嗯,几乎还有几个问题:
-
最短/最快解决方案是什么?这可能并不重要,真的;你应该专注于正确的解决方案,而不是快速解决方案,除非你必须经常这样做,在这种情况下,你应该自动化解决方案,或者重新考虑你的工作流程,这样你就不会一直遇到这个问题。
-
内容应保存在哪里?这个非常重要!如果内容没有价值,问题就会消失,但如果它们有价值,那就太大了。
-
在一个不区分大小写但保留大小写的文件系统上,如果有什么问题的话,你应该怎么做;错案;文件夹?也就是说,Git知道
PATH/TO/FILE
(存储在Git中)需要在PATH
中创建文件夹PATH
和文件夹TO
,然后创建名为FILE
的文件。但是,如果你已经有了一个现有的path
和path/to
,或者PATH/to
,或者其他什么,Git将无法创建一个新的文件夹,它甚至不会尝试,它只会使用";错案;一
最后一个问题可能是最棘手的,有时没有简单的答案,因为你必须决定如何处理问题案例。最大的问题是,当希望同时拥有path/TO/fileA
和path/to/fileB
时,因为实际上不可能拥有。您必须选择一个,并且您可能希望调整您进行的新提交中的文件名。
在我看来,处理最后一个问题的方法是在区分大小写的文件系统上进行Git操作(这在macOS上很容易做到,只需让自己成为区分大小写文件系统,在那里克隆并完成工作),直到一切都安排好。然后,如果你愿意,回到你的不区分大小写的文件系统,去掉现有的工作树(你将这些更改复制到区分大小写文件系统中进行提交,现在就提交了),然后检查提交,这样你就可以得到正确的文件夹大小写。当您在区分大小写的文件系统中工作时,问题本身就不再存在了,所以很容易按照您想要的方式设置所有内容。
这给我们留下了";在哪里保存";问题
我们现在已经将问题归结为一个可解决的问题:您有一些文件需要保存在某个地方。他们有很有价值的数据,你可能想要回来您现在所要做的就是选择保存它们的位置实际上只有两种选择:
- 您可以将它们保存在存储库中(在提交中),或者
- 您可以将它们保存在存储库之外
对于跟踪的文件,前者——将其保存在存储库中——似乎是最好的选择。只需添加并提交数据!它现在处于提交中,只要该提交继续存在,您就可以保存它。如果你愿意的话,在你刚才为此目的创建的一个新的临时分支上进行提交,但如果目标是重新建立基础,我建议你现在添加并提交,然后git reset
额外的提交。
对于未跟踪的文件,选择稍微困难一些。请注意,这些未跟踪的文件可以被忽略,也可以不被忽略,尽管如果它们被忽略,Git有时会随意销毁它们,而你可能根本没有收到这个错误。如果它们不被忽略,你可以很容易地git add
和git commit
它们。如果它们被忽略,您仍然可以添加它们(使用git add -f
)并提交。因此,无论哪种方式,您都可以像对待跟踪文件一样对待它们。棘手的部分是记住稍后取消跟踪它们,尽管git reset --mixed
(默认值)实际上会为您完成所有工作,所以如果您重新设置您所做的额外提交,那么这里实际上没有什么困难。
当然,您的另一种选择是将文件复制或移出存储库。在工作树外创建一个并行目录,然后将它们放在那里。这适用于跟踪和未跟踪的文件,不同之处在于,对于跟踪的文件,您可以复制工作树版本,然后使用git restore
对其进行反修改,而对于未跟踪的文件,只需将其mv
(重命名)到其临时存储区。
结论
您主要需要将文件数据保存在某个位置。换句话说,你需要做Git刚刚告诉你的事情:
Please move or remove [these untracked files] before you [rebase]
除了在这种情况下,您还可以选择添加(可能使用-f
/--force
)并提交未跟踪的文件。然而,在你的情况下,你有最后一个并发症,那就是我说的同样的案例折叠问题是难题:
目录名
pages/Auth
[已变为]小写。。。pages/auth
[和]我希望具有小写名称的目录应用于当前分支20220620_142027_1
。。。
在这里,为自己构建一个区分大小写的文件系统会有很大帮助。
当我们有一些提交时,我们会使用rebase操作,这些提交大部分(或部分)我们认为是可以的,但这些提交有一些我们不喜欢的东西。另请参阅,例如,我对Git交互式rebaseHEAD的回答不指向最后一次提交。在您的情况下,您正在运行一个非交互式:
git rebase master
因为您不喜欢现有提交的一点是,它们不是在分支master
中最后一次提交之后出现的。
但现在你改变主意了。这些提交还有一点你不喜欢,那就是:它们有大写pages/Auth/...
路径。通过为每次提交选择edit
而不是pick
,您可以在单个交互式rebase中解决这两个问题(请再次参阅Git交互式rebase HEAD不指向最后一次提交)。然后--如果您使用的是区分大小写的文件系统--您可以将每个pages/Auth/*
文件的git mv
pages/auth/
,将它们重命名为小写,而不涉及任何问题,查看重命名是否有效,并使用git commit --amend
和git rebase --continue
继续进行下一个要编辑的提交。当rebase完成时,所有名称都将是小写的,完全符合要求。
如果你不能制作一个区分大小写的文件系统,你仍然可以做这项工作,这只是很痛苦。请参阅,例如,在Windows上git git中忽略的文件名大小写更改,在git中更改文件名的大小写,以及在Windows上更改文件大小写?一个简单的git mv
被认为是可以工作的,在许多版本的Git中都可以,但并不能在所有版本中都工作。这里的各种答案提供了各种可以帮助解决问题的方法。
请记住Git最终:
- 只存储文件,而不存储文件夹:文件的名称很长,包括正斜杠,例如
path/to/file
- 区分大小写
Git试图在macOS和Windows上适应不区分大小写的文件系统,并且大部分都做得不错,但如果你能在区分大小写文件系统中工作,整个问题就会消失。
(因为每个提交都保存着每个文件的完整快照,而git rebase
一次复制一个提交,所以你真的必须一次重命名一个提交。你可以完全自动化它,但除非你做了很多,否则没有真正的意义。)