It's not too hard to configure your own repos so they will never commit a change to that path, other repos' owners will have to cooperate to the extent of executing some one-time config commands.
Here's what you do for your own repo:
set up a content filter that will not alter existing content either in the worktree or in the repository.
git config filter.pinned-content.clean 'git show HEAD:%f 2>&- || cat'
git config filter.pinned-content.smudge 'cat %f 2>&- || cat'
git will execute the clean
commands to generate the content to be put in the repo whenever you stage (git add
) such files. Here, the commands try to show what's already committed for the file, and if that doesn't work, if nothing has been committed for it, then they'll take what you're staging. Likewise, git executes the smudge
commands to generate the content that should be put in the worktree on checkout, here using whatever's already there as-is, otherwise taking the content from the repository as a default.
advertise that you want path/to/file treated this way
echo path/to/file filter=pinned-content >>.gitattributes
make the treatment apply to all future checkouts/adds in this repo, even of already-existing commits
mkdir -p .git/info
echo path/to/file filter=pinned-content >> .git/info/attributes
Here's one way to distribute the request and instructions for cooperation:
# commit the new .gitattributes and explain what you need by way of cooperation:
git add .gitattributes
git commit -F- -- .gitattributes <<EOD
How to set up to preserve existing file content
# set up a content filter that will not alter existing content
# either in the worktree or in the repository:
git config filter.pinned-content.clean 'git show HEAD:%f 2>&- || cat'
git config filter.pinned-content.smudge 'cat %f 2>&- || cat'
# make the treatment apply to all future checkouts/adds in this repo
mkdir -p .git/info
echo path/to/file filter=pinned-content >> .git/info/attributes
-------
Please do the above configuration to avoid mistakenly committing local changes
to files marked with the `pinned-content` filter. Currently path/to/file is
marked in the committed `.gitattributes` to be treated this way, you can locally
mark files to be treated this way for even preexisting commits by adding a
similar line to your repository's `.git/info/attributes` file.
EOD
The %f
capability was included in 1.7.4, so it's been four years, it seems reasonable to expect distros have that available.
You can get a very similar effect with git's sparse checkout, but that won't handle supplying default content and can't be enabled through .gitattributes
.
This has passed smoketests and several hours of banging around, it doesn't look much like my first attempt at it.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…