0

I am working on some code in a git repo, and there are several temporary changes I have made which turn off specific events. These changes are only intended to make it easier for me to develop and test the code (including debug output), and should never be committed to the repo. I have a big comment saying this, but I feel like I could do more.

Is there a character string I can include in my code that will prevent a file from being git committed?

I know that git will warn you not to commit code if there is a merge conflict, which is represented by character string, so this functionality does exist. I am wondering If there is a character string specifically intended to simply stop commits.

I want to add some characters to my code, near specific lines that I must remove before I commit my code. Basically, I'm searching for a safety measure which will not allow me to commit the file, and will draw my attention to the location of the code that needs to be remove. .gitignore is not useful in the case. I need to make the change (i.e. flag) within the text of file that I am working on. The file is tracked. I wish for it to remain tracked. Also, I need to specify a line number.

The ability to include the directive within the effected file is needed.

Also

This code should never leave the dev's environment, nor be committed to the repo, nor be included in any feature, nor be included in a release, nor find its way to the test, qa or production server.

Example:

// $this->send_manditory_daily_email();

// Note to future me:
// ABSOLUTLY DO NOT COMMIT THIS TO THE REPO!!!
// IF YOU DO IT WILL CAUSE MAJOR COMPLIANCE ISSUES
// WOW! I WISH THERE WAS A WAY TO PREVENT THIS 
// FILE FROM BEING COMMITTED AS IT IS NOW
Hoyt Jolly
  • 11
  • 3
  • 1
    This is one of the reasons that .gitignore exists. Why isn't is useful? – j08691 Aug 22 '23 at 16:21
  • The file is tracked. I wish for it to remain tracked. Also, I need to specify a line number, and the ability to include the directive within the effected file is needed. – Hoyt Jolly Aug 22 '23 at 16:23
  • 1
    In this cases, I keep those changes in a single commit of a private branch. Then I use `git apply` to put them on and take them off: `git show the-private-branch | git apply - ` and then `git show the-private-branch | git apply -R -` – eftshift0 Aug 22 '23 at 16:36
  • 2
    Sounds like you want a *configuration file* with settings that doesn't get tracked. You can have different config files for development, staging, production etc and load the relevant file based eg on an environment variable – Panagiotis Kanavos Aug 22 '23 at 16:36
  • 1
    My gut feeling is to use a pre-commit hook that blocks the commit if certain text is found in the changes. – TTT Aug 22 '23 at 16:57
  • 3
    This is an X-Y problem, you are trying to accomplish something ( toggleable feature changes / debug behavior / feature bypass without inadvertantly committing it) and instead of just asking the best way to accomplish that, you are asking how to make a tool behave in a way that will enable you to accomplish this goal. Suggest you re-focus on what your true goal is not the hang-up on half-baked solution you have come with as to how to implement it. – UpAndAdam Aug 22 '23 at 17:13
  • Supply a better working solution, or else the half-baked solution will be come the accepted solution. – Hoyt Jolly Aug 22 '23 at 17:21
  • Are you asking about _committing_ or rather _pushing_ those changes? What's bad about committing locally? You could have a hook on the server which will reject those pushes (or a CI pipeline which fails when it sees these changes, thus preventing them from going to production). If it's only your problem and nobody else's on your team, a `pre-push` hook might also be a good starting point – knittl Aug 22 '23 at 17:22
  • This looks promising. Perhaps I could write a hook that searches the files for a specific group of characters, and stops the add operation (or commit or push) if the character string is found. – Hoyt Jolly Aug 22 '23 at 17:32
  • 1
    If you're making "changes" that "should never be committed to the repo" ... then why not JUST CREATE A LOCAL BRANCH???? Give it a scary name like "EXPERIMENTAL". And make sure that puppy never escapes the kennel. – paulsm4 Aug 22 '23 at 17:42
  • If you're not scared of storing your changes to the disk then you should not be any more scared of committing the changes to your repository since there is no functional difference. As for avoiding that your changes land in some *other* repository (like the caonical/central one): it's easier to control that through commit messages (like `TEMP`) or using certain branch names (already suggested) compared to your proposed solution. – Guildenstern Aug 23 '23 at 12:25
  • Trying to avoid committing things *locally* instead of blocking pushes to the canonical repository (on GitHub or somewhere like that) is an uphill battle if there are more than one developer. Compare configuring this local check for a hundred developers vs. doing it once in a pre-receive hook. – Guildenstern Aug 24 '23 at 08:30

3 Answers3

0

Is there a character string I can include in my code that will prevent a file from being git committed?

No, git isn't the right solution here.

I'd advise you to have your local build system insert those local changes during local builds. This way, you can have a clean working directory.

A better solution would be the use of feature flags.

YSC
  • 38,212
  • 9
  • 96
  • 149
  • I'm confused, Which "local changes" are you refereeing to? – Hoyt Jolly Aug 22 '23 at 16:33
  • Those not to be pushed to the repo. – YSC Aug 22 '23 at 16:35
  • Interesting idea, though it might be difficult to create a check that can remove all of the potentially harmful code additions that should not make it into the repo. Debug comments would be easy, but finding essential functionality the might be comment out could be more difficult and error prone. I'd prefer something like a specific string (" >!!> ") that could be added to a comment, which would stop the file from being added or committed until it was removed (after a concern was addressed). Something simple, for a developer self check. That would be Ideal. – Hoyt Jolly Aug 22 '23 at 16:54
  • 1
    with this solution there is nothing to `remove`, the build `adds` the changes in only to a generated file which is built from. – UpAndAdam Aug 22 '23 at 17:05
  • ( Or accomplishes the same through the use of a config file, environement variables etc ) – UpAndAdam Aug 22 '23 at 17:15
  • Feature flags are not quite what I am looking for. The offensive code should never leave the dev's environment, nor be committed to the repo, nor be included in any feature, nor be included in a release, nor find its way to the test, qa or production server. – Hoyt Jolly Aug 22 '23 at 17:38
  • Perhaps the check could be added to a locally run linter code analysis. – Hoyt Jolly Aug 22 '23 at 17:41
0

Yes, you can do this. You can run "filters" on add and checkout that clean up anything that shouldn't be added to the repo and make any changes that might be needed in the work tree.

It feels hacky because it is hacky, this is deep, deep in "it looks stupid but it kinda works" territory, fixing the code to test for a real production environment would be better but if you really have to have locally-modified code nobody knows a better way than this to get it done. That said:

The full docs are in git help attributes for the filter attribute. To do this just for your own use, there's a repo-local attributes file, set up a clean filter for files you're messing with this way and if the damage is reversible, as it looks to be from your question, a smudge filter to re-do the damage.

To make what appears to be the specific change you're after, mark the affected file with the locally-disabled-mandatory-mail filter and have clean and smudge filters that remove and add the commented-out bit (fingers-to-textbox warning, not tested, this is a sketch):

echo affected-file.php filter=locally-disabled-mandatory-email >.git/info/attributes
git config filter.locally-disabled-mandatory-email.smudge \
    'sed -E '\''/\$this->send_manditory_daily_email()/ s,^(//)*,//,'\'
git config filter.locally-disabled-mandatory-email.clean \
    'sed -E '\''/\$this->send_manditory_daily_email()/ s,^(//)*,,'\'
jthill
  • 55,082
  • 5
  • 77
  • 137
  • I feel like we are almost there. Can the filter/hook detect a set of characters in a comment (near the code) instead of the offensive code itself? So within the following comment: ( // do not commit this &!!* ) the '&!!*' character block is detected by git. When these characters are found in a file, the 'add', 'commit' and 'push' operations are halted? – Hoyt Jolly Aug 22 '23 at 18:00
  • You can make the filters do whatever you want, this is code. I'm just showing you how to plug it in so it runs at the right time and where to find the complete docs . – jthill Aug 22 '23 at 18:03
  • Thank, I'm pretty sure that this is what I am looking for. I'll read up on these, and see what I can do with them. – Hoyt Jolly Aug 22 '23 at 18:58
0

I am working on some code in a git repo, and there are several temporary changes I have made which turn off specific events.

Identifying these as temporary changes is correct...

These changes are only intended to make it easier for me to develop and test the code (including debug output), and should never be committed to the repo.

... but no, such changes should absolutely be committed - as temporary commits. I write a lot more details in the answer linked above so I will not repeat all here, only emphasize that if your history while working looks like

pick 10001 Started implementing foo
pick 10002 ==== debug foo ====
pick 10003 Finished implementing foo
pick 10004 Improved bar
pick 10005 ==== debug bar ====
pick 10006 ==== more foo debug ====
pick 10007 Removed unused baz
pick 10008 ==== more bar and foo debug ====

this is trivial to trim down to the following

pick 10001 Started implementing foo
pick 10003 Finished implementing foo
pick 10004 Improved bar
pick 10007 Removed unused baz

when finishing up.

And if you choose ==== as a commit message marker this is not hard to write a pre-push hook to deny pushing, fulfilling the

This code should never leave the dev's environment, ...

requirement (except the "nor be committed to the repo" part which is wrong, it should absolutely be committed as temporary commits).


To emphasize why the question

Is there a character string I can include in my code that will prevent a file from being git committed?

is assuming a wrong solution, think about what happens if a file both has some changes you want to keep permanently while also having some temporary changes that you do not want to keep permanently.

If you completely ignore the whole file you loose the changes you want to keep. The only way to properly handle this is to create two (or more) commits where the changes to keep goes into one and the temporary changes in another commit. That way you can filter out the temporary changes later on.


I know that git will warn you not to commit code if there is a merge conflict, which is represented by character string, so this functionality does exist.

No this is not correct. The presence of conflict markers in a file is merely a symptom of the conflict and not a driving cause. For technical details on git's handling/marking of files in conflict look into the entries printed by git ls-files --unmerged.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
  • The only reason the file is not committed is to give the developer a chance to rereview the file, and after the issue is resolved, commit. Perhaps they should also receive a message telling them that there is an issue the is preventing them form committing, and where the issue is located in the code. – Hoyt Jolly Aug 23 '23 at 19:11
  • Temporary commits could be a better solution. I will need to learn more. – Hoyt Jolly Aug 23 '23 at 19:13