Git: prevent staging some files, automatically stage all
Asked Answered
Z

3

7

I would like to unstage everything in my current working copy, but automatically stage all files and hunks I edit in the future.

For example, I am using a different version of CocoaPods than most other people on the project I am working on. I would like to upgrade the configuration of the configuration files to be compatible with my CocoaPods without breaking theirs. The easiest way to do this is to not include the new configuration in a pull request, but that means I can't build. Stashing and popping won't work because if I stash after editing the configuration and then apply my changes, popping will fix the configuration but undo my changes.

How should I fix this?

Zymogenic answered 8/4, 2016 at 13:26 Comment(5)
I find your question unclear. You want to modify files that are part of the repository, but don't let them be staged when you do a git add? Does using a .gitignore file help you with your problem?Horseleech
Have you considered using a smudge / clean filter instead? That way you could apply your custom configuration on checkout, but you can also ensure your customizations will not get committed.Fargone
@VonC has just added an answer based on what I was proposing :-)Fargone
@Fargone I agree. This looks like a job for a content filter driver.Linkman
Here's a similar question I asked a while ago: #16598757Salsify
L
3

One way would be to modify that configuration file in a way which is visible only by you locally.
But in a way that remains invisible for the other users of that repo.

If those modifications are well defined (and not all over the place in your.config.file) then you could consider a content filter driver in order to generate the right content for that config file on checkout:

(edit or create a .gitattributes file at the root folder of your local repo, and add the line above in it. You can add, commit and push that file: it won't have any impact for other users).

smudge
(image from "Customizing Git - Git Attributes", from "Pro Git book")

cd /path/to/your/local/cloned/repo
git config filter.filterconfig.smudge 'update_config'
git config filter.filterconfig.clean 'restore_config'

The update_config and restore_config scripts can anywhere on your local $PATH (they are in bash, even if you are on Windows, since they will be executed by the mingw git bash).

The update_config script would:

  • make a initial copy of the config file,
  • inject its modifications in the config file.

That way, a git pull which triggers an update of the working tree would automatically re-generate the config file content with the local modifications needed.

And the restore_config script would restore the saved copy of the file whenever it is called by git (it would be triggered by a git status or a git diff for instance):

cat saved_copy

That way, the config file appears to never change as far as git is concerned.

Linkman answered 16/4, 2016 at 19:56 Comment(3)
Your answer is very unclear, referencing things such as both updateconfig and update_config, and two different ways to set them. Please provide clearer step by step instructions (I am not familiar with .gitattributes).Zymogenic
@Coder256 I have change the updateconfig attribute setting name to avoid confusion. It is a configuration name associate to your config file, in order to associate 2 filter driver: one to inject your modifications, one to restore its original content.Linkman
@Coder256 You need both the .gitattributes, and the two (2) git config filter commands in order to activate that filter, and you need to write two bash scripts, one which save the original content to a saved_copy file, and add your modifications, one which will restore its content (one line: cat saved_copy)Linkman
C
2

A strategy I have been using, is to use two branches: One branch that is public, and a second branch that never leaves your machine and which contains your configuration changes.

When you do your development, you have your private branch checked out, but you don't commit to it. Once you are satisfied with your changes, you stash them, checkout the public branch, do a git stash pop, and commit the result. After that, you return to your private branch and merge your fresh commit. The resulting history will look something like this:

*   (HEAD->private) merge
|\
| * (public) commit 3
* | merge
|\|
| * commit 2
* | a change in your local configuration
* | merge
|\|
| * commit 1
* | some private configuration changes
 \|
  * some base commit

Now, if you graph the history of the public branch, you get this:

* (public) commit 3
* commit 2
* commit 1
* some base commit

As you see, no public commit ever depends on your local changes to the configuration, keeping the public history clean of your configuration changes. However, your configuration changes are perfectly version controlled, so you can go back to any of your merge commits and know that you will be able to build.

The price for this is, of course, the hassle of constantly changing branches. So I would avoid such a construct as much as I can, but it can be helpful in some situations.

Charity answered 16/4, 2016 at 20:2 Comment(0)
A
2

Looks like a job for assume-unchanged.

git update-index --assume-unchanged <file>

This will prevent your changes from being staged and commited.

git update-index --no-assume-unchanged <file>

to revert back to normal.

Appling answered 23/11, 2022 at 10:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.