“不更改上演承诺”即使混帐后提交-am B / C的起源与反利用文件名的文件

问题描述 投票:-1回答:1

问题:在两个不同的名称,案件在同一目录下,我不知道前两个文件。所以,我很惊讶地看到这一点,

git commit -am "why"
On branch tmp
Changes not staged for commit:
    modified:   src/view/callCenter/seatReport/SeatSubstate.vue

然后我发现起源有两种SeatSubstate.vue&seatSubstate.vue路径src/view/callCenter/seatReport

但在我的Mac

ls src/view/callCenter/seatReport/
...     seatSubstate.vue /* did NOT show SeatSubstate.vue only seatSubstate.vue */

我知道有关于How do I commit case-sensitive only filename changes in Git?讨论

但我还是不明白,为什么git的不能犯这个文件。

第二,我怎么解决这个问题?例如在SO讨论许多回答中提到git mv对,但我不知道git mv可以解决我的问题或没有。

----- -----更新

我突然意识到我的MAC(我的HD是完全一致)不区分大小写(的APF),是指https://apple.stackexchange.com/questions/71357/how-to-check-if-my-hd-is-case-sensitive-or-not

enter image description here

通常它应该意味着SeatSubstate.vue&seatSubstate.vue是相同的文件,但不知何故混帐使得他们2个不同的文件,从而导致故障。 git mv似乎解决这个问题,但我不是100%肯定。

请参阅Changing capitalization of filenames in Git

git case-sensitive git-remote
1个回答
1
投票

Properly defining the problem

Git是总是能够存储,在提交,在Git的索引,也就是两下,在同一个目录中的两个不同名称的情况下(例如,两者READMEreadme)文件,因为Git不会存储在操作系统文件目录在所有。文件在任何冻结承诺,1这意味着它们保留其形式无论他们是在Linux或Windows或者MacOS或任何其他系统,或者他们是在Git的指数,它实际上只是一个数据file.2中

出现该问题,因为你,人操作的Git,要使用操作系统提供的文件系统,在您的电脑卖场在其正常的日常形式的文件,使您的计算机的其他部分可以与他们合作过。这是不是不合理的要求,Git的内部文件被保存在一个Git,仅供内部形式,即唯一的Git可以使用。你需要能够使用Git的完成某项工作,不只是使用Git玩一整天。

MacOS的必须提供(即可以在同一目录下同时按住READMEreadme),但默认情况下不这样做区分大小写的文件系统的能力。所以,无论是要么不使用MacOS的所有,或通过使用这种能力,一个人,不是你,做了这样的事情:

然后我发现起源有两种SeatSubstate.vue&seatSubstate.vue路径src/view/callCenter/seatReport

换句话说,你有一些现有的提交这两个文件。正如我们刚才所说,Git是完全有能力处理这个。这是你的操作系统是不是。

所以,如果你运行git checkout并选择提交,Git会将这两个文件复制到你的指标,现在有两种拼法,SeatSubstate.vueseatSubstate.vue。它还会将这两个文件(用两种拼法!)你的工作树,但你的操作系统只能容纳一个拼写,所以一个文件擦除等,并留给你的只是一个文件,一个拼写。

当Git的比较索引的文件和它们的工作树中的文件内容及其内容,Git会:

  • 看到的是,根据该指数,有两个文件;
  • 尝试当它打开这个名字比较每个索引文件工作树文件的Git获取;
  • 抱怨说,其中的一个修改。

这里有一个例子,我通过创建一个Unix-y坐标系上的存储库,并给它两个文件,READMEreadme,具有不同的内容,然后克隆提出,到Mac:

sh-3.2$ git clone ssh://[path]/caseissue
...
Receiving objects: 100% (4/4), done.
sh-3.2$ cd caseissue
sh-3.2$ ls
readme

让我们来看看什么是索引:

sh-3.2$ git ls-files --stage
100644 a931371bf02ce4048b623c56beadb9a926138516 0       README
100644 418440c534135db897251cc3ceca362fe83c2117 0       readme

果然,它有两个文件,只是在不同的情况下。让我们来看看什么是这些文件中,什么是在工作树:

sh-3.2$ git show :0:README
I AM AN UPPERCASE FILE
sh-3.2$ git show :0:readme
i am a lowercase file
sh-3.2$ cat readme 
i am a lowercase file

而我们的状态:

sh-3.2$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   README

no changes added to commit (use "git add" and/or "git commit -a")

根据什么我们需要做的,我们也许能够做到这一点,而只知道有关索引,或者我们可能需要直接与指标,这是比较痛苦的工作。


1Technically,冻结文件的内容存储在BLOB对象,他们的名字都存储在树对象,并提交承诺是引用该参考BLOB对象树对象的对象。但是从用户的角度来看,这些文件被冻成了承诺,所以我们可以只使用该措辞在这里。

2The指数实际上可以是多个不同的数据文件,并且可以在备选索引文件指向Git和做各种花哨的技巧与此有关。这是git stash是如何工作的,例如。但“中的”指数是其中的Git构建下一个承诺,你将和我们的目的,这仅仅是文件.git/index


What to do about this if you don't need either file

让我们假设你不需要跟任何一个文件进行工作。如果您需要在区分大小写的方式这两个文件的工作,这样就可以用两个单独的文件名SeatSubstate.vueseatSubstate.vue的内容上做文章,你会很明显,需要建立一个区分大小写的文件系统。但是,无论你做什么,我们可以假设,你不需要任何文件来完成这项工作。

在这里使用的技巧是通过从你的工作树剩下的文件一个开始,然后忽视的事实是Git是告诉你,你有没有上演提交两个变化。也就是说,Git会告诉你,你已经删除这两个文件。

sh-3.2$ rm readme
sh-3.2$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    README
        deleted:    readme

no changes added to commit (use "git add" and/or "git commit -a")

现在,根本就不是在所有使用git commit -a,因为将登台都清除。相反,由于剩余的文件工作(在我的情况下,根本没有),做任何你需要做的,和舞台git add,只是你修改,而不以任何方式接触或者删除的文件的文件。

现在,您可以git commit结果不影响两个文件从你的工作树失踪,但仍出现在新的承诺,你做:

sh-3.2$ echo 'this file is independent of the READMEs' > newfile
sh-3.2$ git add newfile
sh-3.2$ git commit -m 'add new file'
[master 6d5d8fc] add new file
 1 file changed, 1 insertion(+)
 create mode 100644 newfile
sh-3.2$ git push origin master
Counting objects: 3, done.
...
   2dee30f..6d5d8fc  master -> master

在其它(区分大小写的文件系统)的机器上,之后,更新该承诺:

$ ls
newfile readme  README
$ for i in *; do echo -n ${i}: && cat $i; done
newfile:this file is independent of the READMEs
readme:i am a lowercase file
README:I AM AN UPPERCASE FILE

因此,我们完全有能力工作,我们的Mac(或Windows!)系统上,这些提交的:我们只是删除不需要的文件,并小心地避免分期缺失。

What to do about this if you do need one of the files but don't need to change it

现在的问题是有点困难,因为无法与我们的Mac或Windows系统上我们不区分大小写的工作树两种拼法持有这两个文件。

但是,我们可以挑选我们得到的文件!比方说,我们需要的README文件。我们可以看到,我们有替代readme文件之上。因此,我们将删除错误的(当然,我们已经做了),然后输入:

sh-3.2$ git checkout -- README
sh-3.2$ ls
README  newfile
sh-3.2$ cat README 
I AM AN UPPERCASE FILE

如果我们需要,相反,小写之一:

sh-3.2$ rm README 
sh-3.2$ git checkout -- readme
sh-3.2$ ls
newfile readme
sh-3.2$ cat readme
i am a lowercase file

也就是说,我们删除了错误的一个,然后用从索引中抓取一个文件操作git checkout -- path-得到一个文件与我们想要的情况。现在,我们可以使用此文件。但是,我们不能添加或更改它。

What if you need both files, or need to work on one of them?

如果你在同一时间与花哨的命名既需要,你就麻烦了,因为你的操作系统从字面上不能做到这一点,至少不会在这个文件系统;你需要创建一个区分大小写的文件系统,之后,这整个问题消失。但如果你只需要一次一个,做出某种改变,这是我们可以管理,虽然很笨拙。

首先,让我们注意的是,你可以得到一个或两个文件的内容很轻松地:

sh-3.2$ git show :README
I AM AN UPPERCASE FILE
sh-3.2$ git show :readme
i am a lowercase file

(附注::0:README:README意思完全一样的东西来git show串:从指数插槽零下的路径名README文件可以重定向从git show任何你喜欢的文件名的输出,这样就可以同时获得内容。与名字你的操作系统认为“不同”,你可以使用:README:0:READMEgit show。我并不总是我是否用在这里:前缀形式的索引号一致的说法的两个文件,原因是有。:0:形式是,也有级1,2,和在索引3个时隙,仅合并过程中使用。即,如果在索引中的:1:README,这是README的合并基本副本;在一个你将有这冲突合并。)

正如我们上面看到的,你也可以删除工作树文件,并使用git checkout -- <path>让他们中的一个,与你选择的情况下,你的工作树用相同的情况。不幸的是,如果要修改并重新添加的文件,这并不总是有效:

sh-3.2$ rm readme
sh-3.2$ git checkout -- README
sh-3.2$ echo UPPERCASE IS LIKE SHOUTING >> README
sh-3.2$ git add README 
sh-3.2$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   README

哎呀!它好像Git的决定,在工作树的README文件应该更新索引的阶段零readme文件!果然,这正是混帐做的:

sh-3.2$ git show :0:README
I AM AN UPPERCASE FILE
sh-3.2$ git show :0:readme
I AM AN UPPERCASE FILE
UPPERCASE IS LIKE SHOUTING

所以,现在我们必须求助于工具,可以让我们直接写索引。首先,让我们抹去这一变化,并回到“清洁十岁上下”的状态,我们有没有工作树副本。注意:如果你的实际工作是比较复杂的比我的,你可能希望保存所有的在别处git reset抹出来之前!

sh-3.2$ git reset --hard
HEAD is now at 6d5d8fc add new file
sh-3.2$ rm readme 
sh-3.2$ git status --short
 D README
 D readme

--short输出在这里,它在第二位置D字符,显示这两个文件是从工作树丢失,但该指数副本复印件HEAD匹配。所以,现在我们可以得到我们想要的文件,哪一个是 - 我再挑大写之一,因为它出了问题最后一次:

sh-3.2$ git checkout -- README
sh-3.2$ cat README 
I AM AN UPPERCASE FILE

现在,我们使用普通计算机工具与文件的工作:

sh-3.2$ echo UPPERCASE IS LIKE SHOUTING >> README

当我们需要重新添加,但是,我们必须使用git hash-object -wgit update-index

sh-3.2$ blob=$(git hash-object -w README)
sh-3.2$ echo $blob
fd109721431e207046a4daefc9712f1424d7f38f

(这里的echo只是为了说明,表明我们得到了一个散列ID)。现在,我们需要做一个正确格式的索引条目,一拉git ls-files --stage --full-name。也就是说,我们需要相对于树的顶部的完整路径的文件。由于我READMEreadme文件是在树的顶端,在我的情况在这里只是意味着READMEreadme。对于你的榜样,你的两个文件均src/view/callCenter/seatReport,您将需要包括路径名。

在任何情况下,编写Blob对象到Git的数据库,我们现在需要更新索引条目:

sh-3.2$ printf '100644 %s 0\tREADME\n' $blob | git update-index --index-info
sh-3.2$ git status --short
M  README
 M readme

这表明,我们有一个变化上演提交到README和一个没有,readme。这里的长git status如果你喜欢它:

sh-3.2$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme

更直接地说,我们可以用git show查看什么是索引:

sh-3.2$ git show :README
I AM AN UPPERCASE FILE
UPPERCASE IS LIKE SHOUTING
sh-3.2$ git show :readme
i am a lowercase file

这就是我们想要的!所以,现在我们可以git commit结果:

sh-3.2$ git commit -m 'annotate README'
[master ff51464] annotate README
 1 file changed, 1 insertion(+)
sh-3.2$ git push origin master
Counting objects: 3, done.
...
   6d5d8fc..ff51464  master -> master

在对类Unix系统:

$ for i in *; do echo -n ${i}: && cat $i; done
newfile:this file is independent of the READMEs
readme:i am a lowercase file
README:I AM AN UPPERCASE FILE
UPPERCASE IS LIKE SHOUTING

You can always use git hash-object -w and git update-index --index-info

如果你的操作系统是无法拼写文件名或路径名Git的指数法术的方式,你仍然可以与该文件的内容,无论在什么名字,你可以使用工作。这样做之后,你可以使用git hash-object -w把内容制作成冰冻BLOB,准备提交,然后使用git update-index --index-info到BLOB哈希写进指数在期望的分级插槽,通常零下的路径名Git的需求。

你放弃了在这个过程中明智地使用git status,对有问题的文件名使用git add,并在所有使用git commit -a的能力。 Git的需要,使这个更方便,但它永远不会是100%,方便什么;对于这一点,你需要你的操作系统的行为,而不是 - 是重新映射的Git指数路径(不同的)本地操作系统路径,在两个方向的能力:一个名为IP的索引文件,对一些指数路径IP,不应该被假定为在工作树相同的名称,而是其映射名称。映射的名称必须映射唯一回索引路径。 (即,映射应该是在路径上的双射。)

这不仅需要对案件折叠问题,而且对Unicode的问题:MacOS的专卖店在一种形式的文件名,已经归他们,而Linux允许各形式存储的文件名。一个agréable文件命名可以在Linux上有两个名字,但只有一个在MacOS。

© www.soinside.com 2019 - 2024. All rights reserved.