Reputation: 787
I'm working on a project where we have recently started using git. The setup was not perfect from start, so I've set up .gitattributes after people started cloning/working and I'm still making some changes to this file.
Consider the following setup...
Both Alice and Bob have cloned "repo.git" and the repository contains the file /myproj/src/file.ending with \n
as line ending, i.e. the file does not contain \r
characters.
They also both have .gitattributes
with the following setting:
/myproj/src/file.ending -text
This tells git that file.ending
should not be considered a text file and thus no line ending conversion should take place.
Accordingly, the files in Alice's and Bob's working tree also have \n
as line ending.
Now, Alice makes the following change to .gitattributes:
/myproj/src/file.ending text
Alice would like this change to take effect, both for her and for Bob.
The only way I know of right now is quite intrusive:
git rm --cached -r .
git reset --hard
I would like to avoid two things:
What is the preferred way of doing this?
Upvotes: 40
Views: 26005
Reputation: 1
When the .gitattributes is missing in the cloned repo it will not solve the problem of files without the proper attribute - e.g. "eol=lf". The cloned files may have the native eol form and may contradict to tools that process these files.
Upvotes: 0
Reputation: 161
According to https://git-scm.com/docs/gitattributes, this can be done with
git add --renormalize .
Works like a charm.
Upvotes: 13
Reputation: 668
In order to make the changes to take effect you need some kind of git server — for example Gitlab. Push the repo to Gitlab and then create a new folder, cd
into the new folder that you created and then clone the repo into it via
git clone <repository> .
and then changes should be applied correctly.
Like this you avoid the quite intrusive other option that you mentioned.
Upvotes: 0
Reputation: 51
After you have committed the changes for .gitattributes
run the following to apply the changes
git rm --cached -r .
git reset --hard
Upvotes: 2
Reputation: 1705
osse
on irc://chat.freenode.net/#git
gave me this method, and it works reasonably well:
git rm -r :/ && git checkout HEAD -- :/
This will complain if you have uncommitted changes in your tree.
Seems like there should be a better way though.
Upvotes: 12
Reputation: 2879
You don't have to reset hard (if I understand correctly what you're doing).
My case is similiar. I added a .gitattributes
in a running project. I need the files I have and the files in online repo to be ruled by gitattr.
# This will force git to recheck and "reapply" gitattributes changes.
git rm --cached -r .
git add -A
Your commit will re-add all the .ending
files you mention and you'll not lose any changes you may have. Of course, Bob will have to pull to get it.
Upvotes: 27
Reputation: 45659
By "would like this change to take effect", do you mean that Alice wants the working copies to switch to Windows-style line endings for both her and Bob? Then the first problem is, why is Alice taking responsibility for what's in Bob's working tree?
If the file is better described by the new attributes, so be it; the .gitattributes
file can be edited, tested, and committed just like any other.
The procedure you suggest for getting the new attributes to take effect doesn't make a lot of sense, for two reasons:
First, why are you wiping the index? The text attribute affects the relationship between the index and the working copy. In your example it seems it's the working copy you need to change, not the index.
Second, why are you wiping everything from the index? Only the paths whose attributes have changed need to be addressed.
So in your example, if Alice wants to locally reflect the new attributes, the most that should be necessary is
rm myproj/src/file.ending
git checkout -- myproj/src/file.ending
Since this procedure doesn't overwrite the .gitattributes file, there's no need to prematurely commit it.
It's not clear to me what exactly makes Bob unhappy about your original procedure, so I don't know if this one makes him any happier. Perhaps he just wants the update to be automatic when he pulls; while it's not unreasonable to expect that, I'm not sure it's in the cards as git works.
The problem is how changes are detected. In almost every situation, if git's updating the working tree at the end of a merge or fast-forward (e.g. completing a pull), it need only compare the hashes of the indexed objects for the old commit and the new commit to tell if there's a change to apply.
The exception is if attributes (or filter definitions) change - as noted above, that doesn't change the index. But those conditions are relatively rare, and the checks for them are much more expensive than hash check that's right almost every time, so rather than burden every comparison with mostly-pointless costs git allows that when you know you've done certain things, you have to take an extra step.
So if this is going to happen once, just let the team communicate. "The attributes for this path are changing; you may want to refresh your working copies of the affected files."
If it's going to happen repeatedly, my best advice is to figure out why this keeps happening and fix it. You could try to set up some kind of scripted automation, maybe even with hooks, to detect and address attribute changes; but it's a lot of complication and will likely cause more trouble than it fixes.
Upvotes: 6