2

Is it possible to initialize a new git repository inside a non-empty directory and track only files/folders newly added after initializing while ignoring the old ones. For example:

Current folder structure before initializing a new repo:

FolderA/
FolderB/
file1.php
file2.php

After initializing a new repo and creating new files and direcotries:

FolderA/  // old, ignore
FolderB/  // old, ignore
FolderC/  // new, track
file1.php  // old, ignore
file2.php  // old, ignore
file3.php  // new, track
Michael H.
  • 3,323
  • 2
  • 23
  • 31
g5wx
  • 700
  • 1
  • 10
  • 30
  • 2
    Ignoring is done by creating a file called `.gitignore` with specific patterns of files you want to ignore. So I don't think `git init` can directly help you with this specific requirement. – Michael H. Aug 18 '18 at 06:48
  • But maybe the shell command `touch .gitignore; for file in *; do echo $file >> .gitignore; done` could be useful if you execute it directly before `git init`? (should work on Linux/Mac and Git Bash on Windows) – Michael H. Aug 18 '18 at 06:50
  • Should i create .gitignore before the init and define the files to track manually along with excluding all other folders/files? – g5wx Aug 18 '18 at 06:51
  • The shell command above does that. Please try it out and see if that is what you want to do. But just to be clear: git will by default try to track everything _except_ for the files matching a pattern in `.gitignore` files, see https://git-scm.com/docs/gitignore. So you don't need to define which files git shall track, only the ones git shall ignore. – Michael H. Aug 18 '18 at 06:55

4 Answers4

3

Git will only ever track files that you explicitly tell it to using git add. Therefore, there is nothing you need to do: just don't tell Git to track the files you don't want it to track.

This can get annoying if you look at git status, which will then list all untracked files.

There is an easy solution for that, too: just ignore all files:

echo '*' > .gitignore

This will tell Git to ignore all files. You can still add individual files to the repository using git add -f (the -f is necessary to force Git to ignore the fact that the files are ignored).

If you want to use git add . or git add somedirectory to add all new files, then you need to individually list all the files to be ignored in .gitignore. You can use the "annoying" fact I described above, namely that git status will list all untracked files:

git status --porcelain -uall | grep -E '^\?\? ' | cut -d ' ' -f2- > .gitignore

--porcelain specifies the output format for git status to be "Porcelain v1" format. The Porcelain output formats are guaranteed to never change and are designed to be easy to parse by machines, unlike the short or long output formats which are designed to be human-readable and thus may get changed to make them easier to read. -uall tell git status to list all untracked files, otherwise it will only list the directory name if all files in a directory are untracked.

The grep looks for lines beginning with ?? which is how untracked files are listed. The cut then cuts out everything after the ??, which is the file name.

Note: this will break with a file named abc\n?? def.txt, for example. If you have such files, you need to harden the command by e.g. using the -z flag to git status which prints the records delimited by ASCII NUL instead of a newline.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • Fair enough, in theory you can do fine without `.gitignore`. Using `git status` sure can become unpleasant at some point if you choose to work this way. – Michael H. Aug 18 '18 at 07:17
  • Actually, `git status` will list exactly the files you'll want to ignore, so you can easily create a `.gitignore` from that. I'll add that to my answer, I'm currently struggling with making it robust against filenames that contain newlines. (Oh, PowerShell, how I miss you!) – Jörg W Mittag Aug 18 '18 at 11:59
  • 1
    @JörgWMittag: filenames with embedded newlines are particularly evil :-) (they'll break a lot of code-that-is-not-super-careful). Using `-z` is the way to go if possible. – torek Aug 18 '18 at 15:38
0

If you have only small number of files to ignored by git, You can use gitignore functionality of git. To create a simple gitignore follow the steps:

  1. In your repository folder create a file with name .gitignore
  2. Open the file with any text editer such as notepad, notepad++, etc.
  3. List all the files you want to be ignored by git, with name of each file on each seperate line. eg.

    FolderA FolderB file1.php file2.php

For more complex gitignore refer:

You can also use tools such as https://www.gitignore.io/ to generate a gitignore file for you.

Hope this helps.

0

git init itself can not do that, at least not to my knowledge. But a little shell magic can do the trick:

cd /path/to/directory/
touch .gitignore # creates file .gitignore if not yet existing
for file in *; do
    echo $file >> .gitignore
done # appends all the filenames of files in directory to file .gitignore
git init # inits the repository

After the repo has been initialized, you still need to add files (including .gitignore) before committing.

Michael H.
  • 3,323
  • 2
  • 23
  • 31
  • Thanks Michael. My structure was simplified but the real project has over 10k files so adding all of them inside gitignore isn't an option. I'm guessing if i create a new gitignore with excluding all (*) at beginning and then explicity allow specific files/folders (!folderC, !file3.php) etc...should do the trick also? – g5wx Aug 18 '18 at 07:09
  • 10k files _top-level_? That seems weird. Anyway, I guess you can do that though I'm not sure if this is a common pattern to work with git... – Michael H. Aug 18 '18 at 07:15
  • Yep, it works if i create gitignore before init with excluding all (*) and then manually adding the specific files/folders - idea came from your first comment. If you modify your answer i can accept it. Thanks! – g5wx Aug 18 '18 at 07:55
  • Glad I could help. I will not modify my answer this way because even though it works to ignore everything except for some paths, this is not the solution I would recommend. – Michael H. Aug 18 '18 at 10:11
-1

I ended up with excluding all files/folders and included only specific ones. Here is what I did:

  1. Created an empty .gitignore file within the directory root and added * to untrack all the files and folders
  2. Initialized a new repository within that directory
  3. Edited .gitignore by adding specific files and folders to be tracked from this point onwards

My final .gitignore now uses this pattern:

# Ignore everything
*

# Include folders
!/folderC
!/folderD

# Include files
!file3.php
!file4.php

# Include files containing
!*foo*

This workaround seems to be working fine for now. Thanks to Jörg W Mittag and Michael H. answers i was pointed to the right direction.

There were also some useful resources from other SO users:

Make .gitignore ignore everything except a few files

How do I tell Git to ignore everything except a subdirectory?

git ignore filenames which contain

g5wx
  • 700
  • 1
  • 10
  • 30
  • This is the way to go in practice. Note, however, that it's not "being listed in `.gitignore`" that makes a file *untracked*. Untracked-ness is determined solely by whether a file name is in Git's *index*. Using `git add` copies a file from the work-tree, into the index, overwriting the previous one in the index if it was already there, or creating it if not. Either way, the file is now (after add) tracked. If it was in the index before, it's *still* tracked, otherwise it's *now* tracked. – torek Aug 18 '18 at 15:34
  • What `.gitignore` does is mainly just to make `git status` *shut up* about untracked files, and to make en-masse `git add .` *not* add untracked files. But their untracked-ness is still determined by "is that path in the index now?", and the answer to that question is determined one index entry at a time, as of that very moment, based on whether you put the file into the index somehow (e.g., using `git add -f`, or by checking it out of a commit that has it). – torek Aug 18 '18 at 15:36