Home > Net >  how can I add an untracked file in my Github repo?
how can I add an untracked file in my Github repo?

Time:07-22

I have an untracked config.js that stores a few development-mode variables in my local repo and a corresponding config.js on my VPS with the production-mode versions of the same variables. But I want to try out Github Pages. How do I add such an untracked config.js to my Github repository so that it doesn't get replicated when I do a git pull on my laptop? Or, if there is no way I can do this, is there any other way I can achieve this? That is, store some variables separately from the repo but use them for Github Pages website?

CodePudding user response:

You can't. There's a technical wording glitch here, but "you can't" is the short answer. See below for details.

Is there any other way I can achieve this? That is, store some variables separately from the repo but use them for Github Pages website?

There are several options; I have no idea which ones might be good on GitHub Pages specifically. This is, in fact, a Frequently Asked Question from the Git FAQ, where it's disguised as "How to I tell Git to ignore tracked files?":

A common reason to ask this question are configuration files which are added to a project as an example or default, but which individual developers may want to change. Keeping uncommitted changes around is undesirable in the long run, because git diff will always show the changes and they will be added for commit if commands such as commit -a or add -u are used.

This problem can be solved in different ways:

  • Option a: Rename the configuration file to config.template or something like that, and tell the user to use it as a template. The install script for your system could also copy the template configuration to the appropriate location.
  • Option b: Allow configuration options to be overwritten in a seprate file. For example, in Makefiles it is common to add a line -include config.mak, which allows users to add custom configuration in config.mak, rather than changing the Makefile itself.
  • Option c: Make Git ignore changes to the configuration file. There is no automatic centralized way to do that. But on a per-clone basis you can tell Git to do it using either git update-index --assume-unchanged <file> or sparse checkout (see the corresponding section in git-read-tree(1) for details). Note that neither feature was designed for that purpose. Use at own risk.

I generally prefer the "template" option (option A). Your software can typically do something like:

if exists("real-config-file"):
    load("real-config-file")
else:
    print("notice: using template config as fallback")
    load("template-config-file")

and now you get a working system even if you haven't configured it, but once you do configure it, you get a working system with your configuration. The "install script" trick can also copy the template into place as the default initial configuration, provided there's an install phase in whatever system you're using.

The gory details

The phrase tracked file, in Git, refers specifically to any file currently in the index. "The index" is a thing that Git calls by three different names: index, staging area, or cache. I'm using "index" here because of the git update-index command and because the word "index" is relatively meaningless (which means it doesn't drag in too many false assumptions).

The index isn't actually part of any commit, and a repository is primarily a collection of commits. So whether some file exists in some commit or not isn't the right question to ask—at least, not yet. The right question is: How, when, and why do files wind up in the index?

The answer to why is the easiest. A file goes into the index because you would like that file to be in your next commit.

The answer to when and how are trickier, because git add and git rm let you manipulate the index one file at a time, and other Git commands manipulate the index en-masse. The big important ones are perhaps these:

  • The act of checking out a commit, with git checkout or git switch, fills in the index (and your working tree) from a commit.
  • The git reset command (in its "entire commit" mode) can reset the index to match a particular commit. It will do so unless you use --soft.
  • The git merge command uses the index to achieve the merge; the merge result is in the index (and your working tree).

So, if some file is in some particular commit, checking out that commit, or merging with it, will cause that file to wind up in the index. As such, that file will be a tracked file.

But just because some file (index.js or whatever) is in commit a123456 doesn't mean that that file is in commit b789abc. If you switch to commit b789abc and that commit lacks index.js, the file will be removed from the index, if it's there now (provided that the git switch or git checkout succeeds).

The thing is, if it's removed from Git's index, it's also removed from your working tree. That is the effect you wish to avoid. So you must therefore avoid switching away from a commit where the file does exist, and therefore has been put into your index, to a commit where the file does not exist, and therefore is removed from your index and your working tree. Well, except when you want to observe the resulting behavior, which is in fact every time you're using that commit!

So Git is (sort of) doing what you want. It's what you want to want that's not reasonable.

  • Related