3

For some reason, I would like to have an empty file on my repository. The file needs to exists, but the build process changes it, and I do not want those changes to be committed. I need that users that clone my repository ignore changes on this file too.

git update-index --assume-unchanged seems good, but it only works locally.

Do you know how I can solve this ?

azmeuk
  • 4,026
  • 3
  • 37
  • 64

4 Answers4

4

It's easy to set up a repo to preserve a particular committed state for a file, and you can reject anything inbound you don't like.

To preserve a particular committed state for a file:

# do this once when the committed path/to/file is in the state you want
x=`git rev-parse master:path/to/file`
echo path/to/file filter=wired-to-$x >>.gitattributes

# then in each repo that wants it
git config filter.wired-to-$x.clean "git show $x"

The pre-receive hook tests inbound pushes, this simple one

#!/bin/sh
set -e
while read old new ref; do
        git ls-tree $new path/to/file \
        | awk '$3 != "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" {
                print "path/to/file is not empty"; exit 1; }'
done

will reject any push containing an inbound branch tip with a non-empty path/to/file. Sub in your "$x" to check for your desired state, and for added thoroughness you can run through all the inbounds with an inner rev-list loop feeding the ls-tree.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • Your solution seems OK but the main drawback is that users can see most of their commits rejected, because the file is modified at each build. I am looking, if it is possible, for a transparent solution where users just do not care of this file (and do not even know it exists). – azmeuk Oct 16 '13 at 08:35
  • Try it with that clean filter, the only thing your users have to do is that one command, once, and they'll never make a bad commit. – jthill Oct 16 '13 at 08:43
  • So this is great except that the config file is not cloned (which is needed to work). – onionjake Oct 26 '13 at 05:25
  • @onionjake That's intentional on git's part. Your repo is yours. – jthill Oct 26 '13 at 12:42
  • @jthill I understand why git does it, but I believe this is not a complete answer to the question. "I need that users that clone my repository ignore changes on this file too." I think he wants any changes to it to be automatically ignored after a clone without any further action on the users part. This solution will not work unless the users calls the 'git config' command after cloning. – onionjake Oct 31 '13 at 04:55
4

The clean filter approach mentioned by jthill is the right approach. +1

git clean filter

It forces the file to be restored each time it is "added" to the index (meaning it never is actually added, since it hasn't changed).

Problem: How to force users to define it?

Solution: make them clone a template repo, which already contains:

  • that empty file,
  • and the .gitattributes file with the clean filter declared in it

If you set your main centralized repo to deny a ref update which is not a fast-forward one (git config receive.denyNonFastForwards true), your users won't have any choice but to push from a repo with the same common history than your template repo.
That means they will have those settings in place.

Sure they could delete said settings in a new commit, but that is when the pre-receive hooks from jthill's answer kicks in.
If they don't need to know about that files, chances are they won't mess with what was already defined for them.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • +1 for client transparency. Might seem a bit convoluted but this is actually really clean. – George Hilliard Oct 23 '13 at 06:38
  • jthill has the right answer, but I didn't understand it until I read this. – onionjake Oct 26 '13 at 05:01
  • I like your description of the concept, but an actual example would be nice too! – trusktr Feb 21 '14 at 21:21
  • VonC, Your answer and @jthill's seem like they reject pushes to origin when the file is modified... Is there a way so that people can clone your repo with the "template" file in place, but if they make changes to the file those changes will never be committed (almost like .gitignore, except the file exists)? – trusktr Feb 21 '14 at 21:29
1

If they do not git add the changed file then it's not a problem. Teach them not to use git add . and it's near equivalents Difference of “git add -A” and “git add .”.

The project README could also include your git update-index --assume-unchanged instruction for the relevant file(s)

Community
  • 1
  • 1
Philip Oakley
  • 13,333
  • 9
  • 48
  • 71
  • Teaching user could be a solution, but it has no guarantee. I know by experience that a lot of users will not read the README and submit patches with changes on the file I want to freeze. – azmeuk Oct 16 '13 at 08:29
1

This seems like an application's task rather than git's. I would add this file to .gitignore and make sure that build process or any other process that uses it could create it.

lonelyelk
  • 598
  • 9
  • 25