git/list[1] front-page[2] threads[3] people[4] search[5] about
 

RE: A puzzle: reset --hard and hard links

From
rsbecker@nexbridge.com <rsbecker@nexbridge.com>
Date
Jan 24, 2022, 22:18 UTC
Message-ID
<000e01d81170$5f62f600$1e28e200$@nexbridge.com>
In-Reply-To
<xmqqfspc3k8k.fsf@gitster.g>
On January 24, 2022 4:19 PM, Junio wrote:
Show 13 quoted lines
> Michael Herrmann <michael@herrmann.io> writes:
> 
> >> It is merely because you helped Git to realize
> >
> > I don't want to "help Git realize". I'm sorry but in my opinion `git
> > status` should not have any effects on other commands. I don't
> > understand how you can argue that calling `git status` is a valid fix
> > to "help Git".
> >
> >> With another step 1.5 "append a line to the file in question", git
> >> should severe the link,
> >
> > I don't want to sever the hard link. I want to avoid that it gets
severed.
> 
> Sorry, if that is the case, what you want is not a version control, and it
is certainly
Show 19 quoted lines
> not Git.  You want something else.
> 
> Think about this scenario.
> 
>     $ rm -fr one && git init one && cd one
>     $ echo 0 >a; echo 0 >b; git add a b; git commit -m zero
> 
> We have two files, a and b, each of which has "0" in it.
> 
>     $ echo 1 >b; git add b; git commit -m one
> 
> Now they have "0" and "1" respectively.
> 
>     $ echo 2 >a; echo 2 >b; git commit -a -m two
>     $ ln -f a b
>     $ git diff
>     $ git diff HEAD
> 
> Now they have "2".  Since they have identical contents, "diff" would
report no
Show 8 quoted lines
> difference relative to the index or HEAD, even after we manually break the
> working tree by making one of them a hardlink to the other.
> 
> Now, what should this command do?
> 
>     $ git reset --hard HEAD^
> 
> What the user is asking is (1) to move the branch to point at the previous
commit,
> which had 0 and 1 in a and b respectively, and (2) to make sure that the
index and
> the working tree contents match what is recorded in the commit.
> 
> So for Git to be a usefully correct version control system, it is
essential to make
> sure what it writes out would not affect any path other than the one it is
writing
> out.  When it writes "0" to "a", it MUST break the hardlink from elsewhere
that
> points at "a" before it does so.  Otherwise, the "0" it writes into "a"
will also be
> seen elsewhere, which is not what the updated HEAD (i.e. commit "one")
wants to
> see.  The same for "b" when it is updated from "2" to "1"
> when this happens.

I think there are more use cases here than are apparent but also some serious question about why one would do this.

In a Linux/POSIX environment, one can do a hard link to a file inside a git repo, change the file using something like vim, and have git recognize that there is a change in git status. However, this only works on some platforms. Hard links do not have a 100% consistent semantic from one OS to another, one file system to another, or even between editors and scripts. As Junio pointed out, using a > operator on a hard link is likely going to replace the file instead of modifying the existing one. >> might correctly append and have git recognize it in a git status... on some platforms.

Making git consistent in this situation across every possible situation is not only impractical, it is likely impossible and cutting down what git is allowed to do so that only those common things are implemented might gut git badly.

If you are looking for doing external edits while keeping git notified, I would suggest wrapping the file modification in a script that is aware of hard links so that you get the results you want.

Alternatively, a soft link made externally to a physical git file location might do what you want - assuming your platform supports soft links. Your modification script/program/etc. would use the file directly in git instead of the hard link inode, so git is happy. A git status would see the change because the file really only exists in git. Other git operations, like restore, switch, etc., would cause the physical file to be modified correctly, and anything using the referencing soft link would see the change. Note: I am not suggest soft-linking from inside git to outside.

--Randall
Previous: Junio C HamanoNext: Michael Herrmann
Message 11 of 18 in “A puzzle: reset --hard and hard links”
  1. Michael HerrmannJan 19, 2022
  2. brian m. carlsonJan 19, 2022
  3. Junio C HamanoJan 19, 2022
  4. Michael HerrmannJan 20, 2022
  5. brian m. carlsonJan 20, 2022
  6. Michael HerrmannJan 21, 2022
  7. Michael HerrmannJan 24, 2022
  8. Junio C HamanoJan 24, 2022
  9. Michael HerrmannJan 24, 2022
  10. Junio C HamanoJan 24, 2022
  11. rsbecker@nexbridge.comJan 24, 2022
  12. Michael HerrmannJan 24, 2022
  13. Andreas SchwabJan 25, 2022
  14. Ævar Arnfjörð BjarmasonJan 25, 2022
  15. Andreas SchwabJan 25, 2022
  16. Michael HerrmannJan 25, 2022
  17. brian m. carlsonJan 26, 2022
  18. Junio C HamanoJan 26, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.