441

I need to include some files in my GitHub repo, but not track changes on them. How can I accomplish this? An example use case is for a file that includes sensitive user information, such as login credentials.

For example, I deploy a new installation of this framework to a new client, I want the following files to be downloaded (they have default values CHANGEME) and I just have to make changes specific to this client (database credentials, email address info, custom CSS).

// The production config files. I want the files but they need to be updated to specific client needs
application/config/production/config.php
application/config/production/database.php
application/config/production/tank_auth.php
// Index page, defines the environment (production|development)
/index.php
// All of the css/js cache (keep the folder but not the contents)
/assets/cache/*
// Production user based styling (color, fonts etc) needs to be updated specific to client needs
/assets/frontend/css/user/frontend-user.css

Currently if I run

git clone git@github.com:user123/myRepo.git httpdocs

and then edit the files above, all is great. Until I release a hotfix or patch and run git pull. All of my changes are then overwritten.

Moot
  • 2,195
  • 2
  • 17
  • 14
NDBoost
  • 10,184
  • 6
  • 53
  • 73
  • 2
    possible duplicate of [Git: File that must be distributed, but ignored / not reuploaded?](http://stackoverflow.com/questions/5586267/git-file-that-must-be-distributed-but-ignored-not-reuploaded) – Daenyth Mar 21 '12 at 04:07
  • 3
    possible duplicate of [git: can i commit a file and ignore the content changes?](http://stackoverflow.com/questions/3319479/git-can-i-commit-a-file-and-ignore-the-content-changes) – CharlesB Mar 25 '12 at 09:36
  • Possible duplicate of [git: can i commit a file and ignore the content changes?](http://stackoverflow.com/questions/3319479/git-can-i-commit-a-file-and-ignore-the-content-changes) – Tobias Kienzler Mar 23 '17 at 08:36
  • You could just ignore client credential/configuration files and have the program build default files if they are missing when the repo is installed? – MatthewG Feb 04 '20 at 04:39
  • Does anyone know why this obvious mechanism isn't well supported by git? – Nathan Chappell Jan 27 '23 at 14:33

7 Answers7

769

git has a different solution to do this. First change the file you do not want to be tracked and use the following command:

git update-index --assume-unchanged FILE_NAME

and if you want to track the changes again use this command:

git update-index --no-assume-unchanged FILE_NAME

git-update-index documentation

Jon
  • 9,156
  • 9
  • 56
  • 73
nasirkhan
  • 9,948
  • 5
  • 27
  • 33
  • I did what you say but git status keep telling the file is modified – rraallvv Dec 21 '13 at 20:43
  • Works just fine for me. Did you get a message saying "unable to mark file..." when you tried? – shim Jul 08 '14 at 04:33
  • Works over here - finally my 2-stage deployment won't cause constant untracked changes. THANK YOU @nasirkhan !!! – James Cushing Aug 14 '14 at 12:06
  • 47
    As per Junio Hamano (the maintainer of Git): "Assume-unchanged should not be abused for an ignore mechanism. [...] it is not a promise by Git that Git will always consider these paths are unmodified---if Git can determine a path that is marked as assume-unchanged has changed without incurring extra lstat(2) cost, it reserves the right to report that the path has been modified (as a result, "git commit -a" is free to commit that change)." In other words, assume-unchanged is just for local performance issues. If Git can determine that those files changed in a lighter way, it will. – Alejandro García Iglesias Sep 24 '15 at 22:24
  • If anybody else is using a GUI git client, you may need to restart it for it to stop tracking the file you ignored – HeroCC Nov 09 '15 at 22:51
  • 57
    Reading the info for it, I think the `--skip-worktree` option is better suited to this job than `--assume-unchanged`. – PJSCopeland Mar 10 '16 at 23:34
  • 34
    --skip-worktree is indeed the better option. More information: https://stackoverflow.com/questions/13630849/git-difference-between-assume-unchanged-and-skip-worktree# – Customizer Nov 30 '16 at 12:55
  • nasirkhan, can you answer if this affects other users who pull? When I ran it, there was nothing to push – Geoff Lee May 04 '17 at 21:07
  • If you get a message like `fatal: unable to mark file...` it might mean that your file is already ignored (or yet added to the repo) – Pac0 Nov 08 '18 at 14:45
165

To pull an answer out of the comments of another answer:

$ git update-index --skip-worktree FILENAME

Appears to be a better option than --assume-unchanged

More can be read about this here: Git - Difference Between 'assume-unchanged' and 'skip-worktree'

Anthony
  • 13,434
  • 14
  • 60
  • 80
  • 4
    Thanks. Also: [medium.com/@igloude/git-skip-worktree-and-how-i-used-to-hate-config-files](https://medium.com/@igloude/git-skip-worktree-and-how-i-used-to-hate-config-files-e84a44a8c859) – ᴍᴇʜᴏᴠ Jul 05 '18 at 11:36
  • 1
    When I do this and then try to change branches, I get "The following untracked working tree files would be overwritten by checkout...Please move or remove them before you switch branches". Any ideas how to avoid? – Patrick Szalapski Dec 02 '19 at 16:01
  • 1
    The article referenced by @aexl has moved to https://compiledsuccessfully.dev/git-skip-worktree/ – Andrew Keeton Jan 23 '20 at 17:49
  • 6
    The [docs](https://git-scm.com/docs/git-update-index#_notes) say this is a bad idea. "Users often try to use the assume-unchanged and skip-worktree bits to tell Git to ignore changes to files that are tracked. This does not work as expected, since Git may still check working tree files against the index when performing certain operations. In general, Git does not provide a way to ignore changes to tracked files, so alternate solutions are recommended." – Curtis Blackwell Apr 07 '20 at 16:34
68

For my Code Igniter projects, I keep database.php.example and config.php.example in the repo.

Then I add config.php and applications/config/database.php to the .gitignore file.

So, finally, when I deploy, I can copy the .example files (to config.php and database.php), customize them, and they won't get tracked by GIT.

superiggy
  • 1,023
  • 8
  • 14
  • This is not a good solution. If you flush your git index you're going to start tracking changes when you don't mean to. See @nasirkhans answer for the correct way to do this. – Brian Melton-Grace - MSFT Oct 01 '15 at 21:14
  • 3
    I disagree with both previous comments. This way it's much easier to update the "default" values without having to checkout them and copy your local configuration elsewhere just to put it back after. Also, it applies to all repositories so you don't have to do any repeated repo-changes. – OskarD90 Jan 08 '16 at 12:15
  • 1
    if it is in gitignore why would it start tracking changes again – Shapeshifter Nov 04 '16 at 23:25
  • Solves the OP's problem but doesn't really answer the question. – Travis Wilson Oct 12 '17 at 17:15
  • from your answer, now I know what those .example is used for. Thanks sir. – mfathirirhas Dec 22 '17 at 13:11
15

The recommended way, as of git version 2.25.1, is to track templates of the files in the repository, copying them into new files and modifying them locally (ignoring the new filename in .gitignore) (from here):

Users often try to use the assume-unchanged and skip-worktree bits to tell Git to ignore changes to files that are tracked. This does not work as expected, since Git may still check working tree files against the index when performing certain operations. In general, Git does not provide a way to ignore changes to tracked files, so alternate solutions are recommended.

For example, if the file you want to change is some sort of config file, the repository can include a sample config file that can then be copied into the ignored name and modified. The repository can even include a script to treat the sample file as a template, modifying and copying it automatically.

houtanb
  • 3,852
  • 20
  • 21
  • Duplicating files is a reasonable solution. The nature of the problem is that we're trying to maintain different versions of a file on different machines. That is better modeled as completely different files -- one for each machine. Unfortunately, if you need to reference the different file variant from some other common file, you're still stuck with the same problem of having a file that is different across machines. But on the upside, the duplicate file templates create a self-documenting mechanism, and a breakage is less painful. – JamesHoux Jan 07 '22 at 20:17
3

I would put them in your .gitignore file and just copy them manually as needed.

So the skeleton filename would be in git, the ignore filenames would not be in git (but would be in .gitignore). That way, when the manual step to copy them to 'actual' from 'template' (better name than skeleton perhaps) is done they are immediately ignored.

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • 3
    theres no way to add them into the repo first, and then add them to .gitignore? It'd be great if there was a solution for this to include the files but not any changes after a certain commit or something. – NDBoost Mar 20 '12 at 21:08
  • 1
    @mklauber I want to keep them indefinitely until i run `git rm `. The purpose is IE: a config.php file. I want to keep the config file but i obviously dont want to track the database credentials from client to client as they are different. – NDBoost Mar 20 '12 at 21:13
  • 1
    Yes, I have the issue with our rails database.yml file. We keep a skeleton and then copy and change it. – Michael Durrant Mar 20 '12 at 21:15
  • if i create these "Skeleton" config files, would you be adding them to an initial commit. and then modifying .gitignore to ignore the file? In effect keeping the file in the repo but as a skeleton? – NDBoost Mar 20 '12 at 21:21
  • 12
    You have these two options: Add the file by `git add file1` and then edit your `.gitignore` file. The commited file will stay in there and not be updated. Or: You can add the file to `.gitignore` and then add it with `git add --force file1` to force the file in. You can use the 2nd option whenever you have to overwrite the file – klaustopher Mar 20 '12 at 21:26
  • skeleton filename would be in git, the ignore filenames would not be in git (but would be in git ignore). That way, when the manual step to copy them to 'actual' from 'template' (better name than skeleton perhaps) is done they are immediately ignored. – Michael Durrant Mar 20 '12 at 21:51
2

The answers given are solving the problem just partially, but introducing even more problems.

I needed to preserve the"Web.Local.config" file. The only solution that worked for me was to:

1. Exclude the file from the project

2. Create a separate copy of the file as Web.LocalTemplate.config

Now that "Web.LocalTemplate.config" is tracked by Git, all developers can use it as a starting point. However, the "Web.Local.config", not being part of the project will be automatically ignored.

Hrvoje Matic
  • 1,207
  • 15
  • 12
  • 2
    How is `git update-index --skip-worktree FILENAME` only solving your problem partially, or even adding more problems?? It solves exactly what you're trying to do. Did you try it? – Amir Asyraf Jul 23 '19 at 11:55
1

Make sure to add "full path for filename" (relative path from root)

git update-index --skip-worktree FILENAME.

If you do not give the full path for the file. It will give an error

fatal: Unable to mark file response.json

Harsh Boricha
  • 93
  • 1
  • 7