{"thread":{"id":"61128","subject":"[Idea] Only allow commits when no undeletable file has been deleted","startedAt":"2024-03-15T19:00:57Z","lastAt":"2024-03-15T20:41:16Z","messageCount":2,"participants":["leon","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"490704","messageId":"5f4701bf-3121-4c78-90c8-b1f3a942512b@kske.dev","threadId":"61128","inReplyTo":null,"subject":"[Idea] Only allow commits when no undeletable file has been deleted","fromName":"leon","fromEmail":"leon@kske.dev","sentAt":"2024-03-15T18:55:37Z","receivedAt":"2024-03-15T19:00:57Z","isPatch":false,"sender":{"key":"leon@kske.dev","avatar":null},"body":"Hello,\n\nI have an idea for a feature I am missing often enough within Git (and \nit **needs** to be part of Git itself as it would be rather useless \nwithin third-party tools):\nOftentimes, when you have submodules, you are depending on specific \nfiles being present within them, i.e. so that your Shell scripts and/or \nCI tools work correctly.\nHowever, especially when the submodule is under your own control, you \ncurrently have no option to tell future collaborators that deleting or \nrenaming such a file will break things.\nOr even your future self, FWIW.\nSo, what if there was a recognized attribute within the `.gitattributes` \nthat said `files matching this path spec cannot be deleted`?\nThe actual content of the file is irrelevant as long as it exists.\nI don't care how this attribute is called in the end and cannot think of \nany good name.\nMy best approach was something like `depended-on-externally` or \n`undeletable`.\n\nMy proposed behavior is thus the following:\n- Git stores the list of files from HEAD that may not be deleted somehow \n(probably best to compute it on the fly when necessary)\n     - To allow for deleting a file in the same commit as removing its \n`.gitattribute` entry, the list of files that cannot be deleted depends \non the `.gitattributes` as it should be committed.\n- When you try to create a commit, all undeletable files are checked for \nif they still appear in the tree\n- If files are no longer present in the tree, the commit is aborted with \nan error message telling the user something like `You are trying to \ndelete the undeletable file <x>/ files <x, y, z>. Either restore \nit/them, or remove <corresponding path specs> from the '.gitattributes'`\n- In particular, this means the following behavior for changes:\n     - Adding a new file: Nothing to do\n     - Deleted file: Checking if it can actually be deleted\n     - Renamed file: Checking if another file replaced it\n- No idea how to handle path specs pointing inside submodules. I'm fine \neither way:\n     - Path specs going into submodules are ignored (more performant, \nplus you cannot influence them directly)\n     - Path specs going into submodules are checked too (helps catch \nbugs early as an error can only happen when you update the submodule. As \nsuch, you'll quickly know that you just broke something)\n\nDrawbacks of this approach:\n- `git commit` will be slower. Don't know how much, probably depends on \nthe implementation\n\nAdvantages:\n- You can ensure that you don't accidentally break something in other \nrepos (or even your own, if you have enough dependencies on your own \nfilenames…)\n\nSo, what do you think?\n\n"},{"id":"490736","messageId":"ZfSyakFaxHyTEdxR@tapette.crustytoothpaste.net","threadId":"61128","inReplyTo":"5f4701bf-3121-4c78-90c8-b1f3a942512b@kske.dev","subject":"Re: [Idea] Only allow commits when no undeletable file has been deleted","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2024-03-15T20:41:14Z","receivedAt":"2024-03-15T20:41:16Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2024-03-15 at 18:55:37, leon wrote:\n> Hello,\n> \n> I have an idea for a feature I am missing often enough within Git (and it\n> **needs** to be part of Git itself as it would be rather useless within\n> third-party tools):\n> Oftentimes, when you have submodules, you are depending on specific files\n> being present within them, i.e. so that your Shell scripts and/or CI tools\n> work correctly.\n> However, especially when the submodule is under your own control, you\n> currently have no option to tell future collaborators that deleting or\n> renaming such a file will break things.\n> Or even your future self, FWIW.\n> So, what if there was a recognized attribute within the `.gitattributes`\n> that said `files matching this path spec cannot be deleted`?\n> The actual content of the file is irrelevant as long as it exists.\n> I don't care how this attribute is called in the end and cannot think of any\n> good name.\n> My best approach was something like `depended-on-externally` or\n> `undeletable`.\n\nI think you want something more than \"undeletable\".  If I change your\n`script/build` file to contain only \"Kilroy was here\", it's still not\ngoing to work, since that's neither a valid script nor a valid\nexecutable.  I certainly haven't deleted it, but I've rendered it\nunusable nonetheless.  This sounds like a contrived example, but it's\nentirely possible for people to typo a filename using completion and\nsave the wrong thing to the wrong file or redirect the output of a\nprogram to the wrong place accidentally.  We've all done it.\n\nI think this is a great place for a CI job, though.  If you know these\nfiles are required, you can add a cheap CI job that simply checks to see\nwhether the files are valid scripts (or whatever policy you'd like to\nhave) and fails early on.  You can even make other CI jobs depend on it\nso that you don't waste a lot of time failing all the other CI jobs when\ntheir files are missing.\n\nOne thing I've also seen that we have at work is that you can link CI\njobs for project A to project B.  Thus, if project B is a dependency of\nproject A, changes to project B run its own CI jobs plus a standard\nproject A CI job, to verify that nothing's broken.  This is really\nuseful and a great way to avoid breaking things in more subtle ways\n(e.g., removing a function that you didn't think you needed, but project\nA does, or changing the behaviour of a function in a way that breaks\nother projects).\n-- \nbrian m. carlson (they/them or he/him)\nToronto, Ontario, CA\n"}]}