0

Let us suppose I want to make sure that there will be a folder called foo and a file inside it called bar. After I have made sure foo/bar exists I do not intend to version it, therefore I add it to .gitignore.

Bullet-proof approach:

  • create foo
  • create foo/bar
  • commit
  • push
  • deploy
  • add foo to .gitignore
  • commit
  • push
  • deploy

Shorter approach:

  • create foo
  • create foo/bar
  • commit
  • add foo/bar to .gitignore
  • commit
  • push
  • deploy

I wonder whether the shorter approach is guaranteed to create the folder, file and to ignore it. I have done a test and the result seemed to confirm my assumption that the shorter approach will add foo/bar at remote locations as well and then stop versioning it. Is this a rule applicable to all versions?

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • What's wrong with short approach? it's all applied via 1 push anyway. – divix Oct 29 '16 at 14:05
  • @divix, the long approach includes a push and deploy before changing .gitignore. I am not saying the short approach is wrong, in fact my experiment makes me thing it is not wrong, but I do not factually know that. – Lajos Arpad Oct 29 '16 at 14:06
  • 1
    when a file is already follow whatever in .gitignore will be ignore to this file. .gitignore only apply when you add new file. – Stargateur Oct 29 '16 at 14:06
  • @Stargateur, when I deploy to a server, .gitignore will be changed and the folder and file should be put there. I just wonder whether there is any possibility that .gitignore is applied before the creation of the folder and file. So far I think there is no such possibility, but I do not factually know that, hence my question. – Lajos Arpad Oct 29 '16 at 14:08
  • @LajosArpad git add -f ? – Stargateur Oct 29 '16 at 14:11
  • @Stargateur, that is an alternative indeed, but that is an approach to bypass the mechanism I wonder about. – Lajos Arpad Oct 29 '16 at 14:15
  • Create an empty `foo/.gitignore` and commit that instead. – Thorbjørn Ravn Andersen Oct 29 '16 at 14:37
  • Also the "deploy to a server" should not change the source files - this will cause you pain. Just let your package step add the files you need. – Thorbjørn Ravn Andersen Oct 29 '16 at 14:38
  • @ThorbjørnRavnAndersen, I understand you consider the approach described better for some reason and you might be right, but I wonder if I deploy two commits and the earlier commit contains the folder and file creation, the latter modifies .gitignore, is there any chance that .gitignore modification will be executed before folder and file creation is taken into account? I try to understand how .gitignore works under the hood and work-arounds will not help me to do so. – Lajos Arpad Oct 29 '16 at 14:42
  • `.gitignore` just tells git what files not to consider _in the file system_. It does not affect files already in the repository. – Thorbjørn Ravn Andersen Oct 29 '16 at 22:44
  • Also git only deals with files. Directories are just a side effect and does not have special treatment. – Thorbjørn Ravn Andersen Oct 29 '16 at 22:46

1 Answers1

1

As the commenters have noted, if you add a file-path to a .gitignore file after the file is committed, it's too late.

You have two different questions combined into one, here:

  1. How do I convince Git to create an empty directory? (This is your practical problem, the one you need to solve for what you're doing.)

  2. How does .gitignore actually work? What rule(s) apply what actions and when? (This is what you are asking in your subject line.)

For item 1, see How can I add an empty directory to a Git repository?

For item 2, see https://git-scm.com/docs/gitignore. Let me extract this sentence from there and put it in bold, though: Files already tracked by Git are not affected. If you've git add-ed a path that would be ignored, it is not ignored. To get it to become ignored, you must explicitly remove it, which has its own pitfalls. See How to stop tracking and ignore changes to a file in Git? and How to make Git "forget" about a file that was tracked but is now in .gitignore?

Note that when dealing with accidentally tracked configurations, that cannot now be removed, via git update-index, the modern recommendation is --skip-worktree, not --assume-unchanged.

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • I believe you misunderstood the question. I am not dealing with empty directories. In the question I have described that I create a foo folder and a bar file inside it. The idea is to create the folder and file and only then add the folder to gitignore. The file could contain settings specifiable by all members of the team, each of them to their liking and a default content at commit time. – Lajos Arpad Oct 30 '16 at 08:37
  • The question seeks answer to the situation when a git repo does not have the file yet and receives two commits: one which creates the file in the folder and another which adds the folder to gitignore. I wonder whether there is any chance that the second commit, modifying .gitignore is saved before the file is being created, ignoring it. – Lajos Arpad Oct 30 '16 at 08:39
  • But you talk about creating a directory (which, since you just created it, must be empty), then creating a file within that directory, then committing. If you have not added the file, Git does nothing with the directory. If you *have* added the file, Git adds the file (which lives within the directory). Remember that Git does not store directories, only files; it *creates* directories when and if needed, later, in order to *check out files* (as stored in commits). – torek Oct 30 '16 at 08:50
  • torek, I would not talk about the creation of a file if it was not added. You assume that the question is about empty directories, which is not the case. The directory is not empty under any means. It either exists along with its file and then ignored or is never created due to .gitignore rules. I am wondering whether there is any chance that .gitignore change will be applied before the creation of the directory. – Lajos Arpad Oct 30 '16 at 08:58
  • And if you read the question again, you will see that there is a bullet-proof longer approach which will work well even if git would consider the latter commit earlier when it comes to file changes if both commits are received at the same time. I wonder whether the shorter approach is just the same. My experiment confirmed it is, but that is only empirical knowledge and I wonder whether it is a rule to make file changes in an earlier commit before a later commit, or my experiment's result was by chance. – Lajos Arpad Oct 30 '16 at 09:01
  • Let's try a completely different approach. Are you aware of the fact that Git creates directories *only when it must*? That is, if you move to a commit that that has path `d/b` (from one that lacks it), Git must extract file `d/b`, which requires directory `d` to exist. If the directory already exists in the work-tree, Git leaves it alone. If the directory does not exist yet, Git creates it. That is the *only* time Git creates a directory: when it goes to extract a file into the work-tree and needs to create the directory in order to do so. – torek Oct 30 '16 at 09:32
  • The question to be asked is therefore not about *repository* contents, but rather about *work-tree* contents, when *changing* from one commit to another (via `git checkout`). A work-tree is always "at" some commit, with the exception of a new empty repository that has no commits at all. The current commit is recorded in `HEAD` and in Git's "index" (`.git/index`). There are some difficult corner cases when the index is out of sync with the current work-tree contents, but in deployment setups the index should match the work-tree. Deployment scripts tend to break when this is not the case. – torek Oct 30 '16 at 09:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126994/discussion-between-torek-and-lajos-arpad). – torek Oct 30 '16 at 09:47