There are instances where I can't use a .gitignore
file, otherwise, on git push
, critical files are purged from the remote. In these cases, I apply git update-index --assume-unchanged <file>
to the files that I want to ignore.
After applying the assume-unchanged rules and calling git push
, will these rules be attached to the remote branch so that all subsequent pulls (from other clients) will inherit them? Or, must these clients also run the git update-index --assume-unchanged <file>
commands individually at their machines?
If the commands are not inherited -- has anybody written a server hook for this before? Instead of mandating that all current and future clients safeguard against it?
Runs git update-index itself on the paths whose index entries are different from those from the HEAD commit. Restores the unmerged or needs updating state of a file during a merge if it was cleared by accident.
git/index changed by windows. So it can only refresh the index and replace the . git/index file, which makes the next git status super fast and git status in windows very slow (because the windows system will refresh the index file again).
The index is local to your workstation, any changes you make there do not propagate to other clones of the same remote.
(updated, after question was updated)
There are instances where I can't use a .gitignore file, otherwise, on git push, critical files are purged from the remote.
This is not true. The git ignore file does not affect files that are already tracked in the repository. If you add a file to .gitignore
after it has been committed, it'll stay inside the repository; it will not be purged. In fact, it behaves pretty much as if it weren't ignored at all.
You can easily check this in a temporary repository:
$ mkdir -p /tmp/repo $ cd /tmp/repo $ git init Initialized empty Git repository in /tmp/repo/.git/ $ echo red > a.txt $ git commit -am '1' 1 file changed, 1 insertion(+) create mode 100644 a.txt $ echo a.txt > .gitignore $ echo b.txt >> .gitignore $ git commit -am '2' 1 file changed, 2 insertions(+) create mode 100644 .gitignore
The repository now contains two files: a.txt
and .gitignore
. Both behave normally, which you can see when you clone it:
$ cd .. $ git clone file://repo repo2 $ ls -A repo2 .git .gitignore a.txt $ cd repo
If we modify both ignored files and request git status
, we'll see that a.txt
is seen as modified, despite having been gitignored. We can add and commit it as normal; in fact, if you add an tracked file to gitignore, it behaves pretty much like it's not in gitignore at all.
$ echo green > a.txt $ echo blue > b.txt $ git status --short M a.txt $ git add a.txt
The b.txt
file is different, because it was ignored before git started tracking it. This file will not normally make it into the repository, but we can force it if we want to.
$ git add b.txt The following paths are ignored by one of your .gitignore files: b.txt Use -f if you really want to add them. fatal: no files added $ git add -f b.txt
Issuing git commit
now commits two files that have both been git ignored:
$ git commit -m '3' 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 b.txt
Long story short, think of git ignore rules as guidelines :-)
After applying the assume-unchanged rules and calling git push, will these rules be attached to the remote branch so that all subsequent pulls (from other clients) will inherit them? Or, must these clients also run the git update-index --assume-unchanged commands individually at their machines?
The latter. Closest you can get is add a shell script to the repository that makes the changes for you.
If the commands are not inherited -- has anybody written a server hook for this before? Instead of mandating that all current and future clients safeguard against it?
If your aim is to write a server hook that removes the critical files as if they weren't part of the push at all, that's not possible. Git push deals primarily with commit objects (and refs). Their dependent objects, like trees and blobs, are transferred as needed, subject to reachability from a commit. What it boils down to is that, if it's not committed, you can't push it to a remote (that's an oversimplification, but it holds true for the files in the repository). In addition, git commits are cryptographically guarded. You can't change a commit without changing its commit hash, and if you change the commit hash, you basically have a different, new commit (that may happen to have the same diff as the old one).
This means that the server can't rewrite commits; at least not without seriously confusing the client that did the push (which will still have a copy of the old commit objects).
What you can do is write a post-receive hook that refuses the commits if they contain the files you don't want to have updated. This doesn't really solve your problem, because if you have trouble explaining git commit --assume-unchanged
to your coworkers, then you'll likely have even more trouble explaining how they can use interactive rebase to recreate their commits without the undesirable files in them.
Long story short, I think chasing everybody to keep using assume-unchanged (maybe combined with a post-receive hook) is your least bad choice if you're dealing with files that should be committed once and never thereafter, like you have now.
Your life would become a whole lot easier if you can keep these files out of git in their entirety. One of the things I can think of:
.gitignore
the files in their definitive location, the one where they have to be but get unwanted changes all the timeIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With