threads / discuss / 52971

new file mode 160000

Subject: new file mode 160000

## tl;dr

9 messages between Mar 10, 2020 and Mar 11, 2020.

replies: 8people: 5as markdown or json

Jörn Engel· Mar 10, 2020, 18:41 UTC · lore

Something weird happened to us and I have no idea how to reproduce it. A developer managed to create a git commit with the following content:

diff --git a/foo b/foo
new file mode 160000
index 000000000000..b7e7816c1266
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+one line of content

File name and content obfuscated, the rest is verbatim from the git
commit.

Now, file mode 160000 doesn't make sense to me.  It doesn't correspond
to any known file type and I cannot explain how this commit was created
in the first place.  But whatever the mechanism, the git client should
have refused it.

Next, the commit was pushed to our git server, which happily accepted
it.  Again, I would argue that the git server should have refused the
push.

Finally, others including myself pulled and checked out a branch with
this commit.  On checkout, an empty directory is being created and
caused various mayhem.  I get:
	error: 'foo' does not have a commit checked out
	fatal: updating files failed

Not sure what the correct solution would be here.  An empty directory is
a bad idea, but I cannot think of any "correct" way to handle things
once the bad commit is in the tree.

In case it matters, my client is: git version 2.25.0

Jörn

--
So, one might well ask, if Congress and the White House, Republicans
and Democrats, liberals and conservatives, all now agree on reform,
how meaningful can the reform be?
-- David Cole
Andreas Schwab· Mar 10, 2020, 19:10 UTC · re: Jörn Engel · lore

Re: new file mode 160000

On Mär 10 2020, Jörn Engel wrote:
Show 15 quoted lines
> Something weird happened to us and I have no idea how to reproduce it.
> A developer managed to create a git commit with the following content:
>
> diff --git a/foo b/foo
> new file mode 160000
> index 000000000000..b7e7816c1266
> --- /dev/null
> +++ b/foo
> @@ -0,0 +1 @@
> +one line of content
>
> File name and content obfuscated, the rest is verbatim from the git
> commit.
>
> Now, file mode 160000 doesn't make sense to me.

0160000 is S_IFLNK in MiNT <https://github.com/freemint/freemint/blob/master/sys/mint/stat.h>.

Andreas.
-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."
Junio C Hamano· Mar 10, 2020, 19:47 UTC · re: Andreas Schwab · lore

Re: new file mode 160000

Andreas Schwab <schwab@linux-m68k.org> writes:
Show 20 quoted lines
> On Mär 10 2020, Jörn Engel wrote:
>
>> Something weird happened to us and I have no idea how to reproduce it.
>> A developer managed to create a git commit with the following content:
>>
>> diff --git a/foo b/foo
>> new file mode 160000
>> index 000000000000..b7e7816c1266
>> --- /dev/null
>> +++ b/foo
>> @@ -0,0 +1 @@
>> +one line of content
>>
>> File name and content obfuscated, the rest is verbatim from the git
>> commit.
>>
>> Now, file mode 160000 doesn't make sense to me.
>
> 0160000 is S_IFLNK in MiNT
> <https://github.com/freemint/freemint/blob/master/sys/mint/stat.h>.
Yeek.  That sounds like a ticking time-bomb.
Andreas Schwab· Mar 10, 2020, 20:09 UTC · re: Junio C Hamano · lore

Re: new file mode 160000

On Mär 10 2020, Junio C Hamano wrote:
Show 24 quoted lines
> Andreas Schwab <schwab@linux-m68k.org> writes:
>
>> On Mär 10 2020, Jörn Engel wrote:
>>
>>> Something weird happened to us and I have no idea how to reproduce it.
>>> A developer managed to create a git commit with the following content:
>>>
>>> diff --git a/foo b/foo
>>> new file mode 160000
>>> index 000000000000..b7e7816c1266
>>> --- /dev/null
>>> +++ b/foo
>>> @@ -0,0 +1 @@
>>> +one line of content
>>>
>>> File name and content obfuscated, the rest is verbatim from the git
>>> commit.
>>>
>>> Now, file mode 160000 doesn't make sense to me.
>>
>> 0160000 is S_IFLNK in MiNT
>> <https://github.com/freemint/freemint/blob/master/sys/mint/stat.h>.
>
> Yeek.  That sounds like a ticking time-bomb.
configure can detect that (NEEDS_MODE_TRANSLATION).
Andreas.
-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."
Junio C Hamano· Mar 11, 2020, 18:35 UTC · re: Andreas Schwab · lore

Re: new file mode 160000

Andreas Schwab <schwab@linux-m68k.org> writes:
Show 6 quoted lines
>>> 0160000 is S_IFLNK in MiNT
>>> <https://github.com/freemint/freemint/blob/master/sys/mint/stat.h>.
>>
>> Yeek.  That sounds like a ticking time-bomb.
>
> configure can detect that (NEEDS_MODE_TRANSLATION).
Thanks--I totally forgot about that one.
Bryan Turner· Mar 10, 2020, 19:37 UTC · re: Jörn Engel · lore

Re: new file mode 160000

On Tue, Mar 10, 2020 at 11:41 AM Jörn Engel <joern@purestorage.com> wrote:
Show 19 quoted lines
>
> Something weird happened to us and I have no idea how to reproduce it.
> A developer managed to create a git commit with the following content:
>
> diff --git a/foo b/foo
> new file mode 160000
> index 000000000000..b7e7816c1266
> --- /dev/null
> +++ b/foo
> @@ -0,0 +1 @@
> +one line of content
>
> File name and content obfuscated, the rest is verbatim from the git
> commit.
>
> Now, file mode 160000 doesn't make sense to me.  It doesn't correspond
> to any known file type and I cannot explain how this commit was created
> in the first place.  But whatever the mechanism, the git client should
> have refused it.

Git's file modes aren't (entirely) real. It doesn't actually track read/write, for example, but it does use the mode to track executable. That means, for normal files, the possible modes are 0755 and 0644. Other modes like 0600 or 0750 or similar are not possible.

But Git also uses the mode as a way to track other things. In this case, 160000 means the file is _intended_ to be a submdule (albeit with what appears to be invalid content for a submodule, in this case). Relevant source: https://github.com/git/git/blob/master/cache.h#L69

>
> Next, the commit was pushed to our git server, which happily accepted
> it.  Again, I would argue that the git server should have refused the
> push.
Since 160000 is a valid mode _to Git_, the push is fine.
Show 6 quoted lines
>
> Finally, others including myself pulled and checked out a branch with
> this commit.  On checkout, an empty directory is being created and
> caused various mayhem.  I get:
>         error: 'foo' does not have a commit checked out
>         fatal: updating files failed

This indicates, as I mentioned earlier, that the contents of the "foo" submodule are invalid, so Git couldn't actually check it out. The content is expected to be the SHA of a commit, paired with a matching line in a `.gitmodules` file which tells Git where the repository is so it can check it out.

>
> Not sure what the correct solution would be here.  An empty directory is
> a bad idea, but I cannot think of any "correct" way to handle things
> once the bad commit is in the tree.

It should be straightforward to delete the broken submodule (git rm foo), commit and push.

Hope this helps! Bryan

>
> In case it matters, my client is: git version 2.25.0
>
> Jörn
Junio C Hamano· Mar 10, 2020, 19:46 UTC · re: Jörn Engel · lore

Re: new file mode 160000

Jörn Engel <joern@purestorage.com> writes:
Show 15 quoted lines
> Something weird happened to us and I have no idea how to reproduce it.
> A developer managed to create a git commit with the following content:
>
> diff --git a/foo b/foo
> new file mode 160000
> index 000000000000..b7e7816c1266
> --- /dev/null
> +++ b/foo
> @@ -0,0 +1 @@
> +one line of content
>
> File name and content obfuscated, the rest is verbatim from the git
> commit.
>
> Now, file mode 160000 doesn't make sense to me.

These are gitlinks, that are used to implement submodules. I cannot tell if this is an expected behaviour and there is nothing to worry about, or you found a corner case bug, without looking at what the "one line of content" says, but if it says "Subproject commit " followed by 40-hex object name, then that is a perfectly normal behaviour.

After doing these:
	git init bar
	cd bar
	git init foo
	cd foo ;# in bar/foo
	git commit --allow-empty -m initial
	cd .. ;# back in bar
	git add foo
	git commit -m add
	git show

anybody who has a working Git would see the "diff --git" that shows 160000 you showed above.

Jörn Engel· Mar 10, 2020, 19:57 UTC · re: Junio C Hamano · lore

Re: new file mode 160000

On Tue, Mar 10, 2020 at 12:46:06PM -0700, Junio C Hamano wrote:
Show 24 quoted lines
> Jörn Engel <joern@purestorage.com> writes:
> 
> > Something weird happened to us and I have no idea how to reproduce it.
> > A developer managed to create a git commit with the following content:
> >
> > diff --git a/foo b/foo
> > new file mode 160000
> > index 000000000000..b7e7816c1266
> > --- /dev/null
> > +++ b/foo
> > @@ -0,0 +1 @@
> > +one line of content
> >
> > File name and content obfuscated, the rest is verbatim from the git
> > commit.
> >
> > Now, file mode 160000 doesn't make sense to me.
> 
> These are gitlinks, that are used to implement submodules.  I cannot
> tell if this is an expected behaviour and there is nothing to worry
> about, or you found a corner case bug, without looking at what the
> "one line of content" says, but if it says "Subproject commit "
> followed by 40-hex object name, then that is a perfectly normal
> behaviour.
That is indeed the content.  So no bug in git.  Thank you!

Given that we don't want to use submodules for this particular project, can the git server be configured to refuse push requests that would introduce submodules?

Jörn

-- This above all: to thine own self be true. -- Shakespeare

brian m. carlson· Mar 10, 2020, 22:22 UTC · re: Jörn Engel · lore

Re: new file mode 160000

On 2020-03-10 at 19:57:24, Jörn Engel wrote:
Show 5 quoted lines
> That is indeed the content.  So no bug in git.  Thank you!
> 
> Given that we don't want to use submodules for this particular
> project, can the git server be configured to refuse push requests that
> would introduce submodules?

I don't believe there's an option to do this, but it could be achieved with a pre-receive hook. That's the usual approach for denying pushes containing unwanted data (submodules, large files, commits with improperly formatted messages, etc.).

If your Git server doesn't let you install pre-receive hooks, you can do this by adding a test to your CI system to reject objectionable pushes.

-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204

← back to recent threads