I want to have two directories in one git repository.
My method of choice is to create a git repository in a top-level directory and then use .gitignore to whitelist the two directories of interest.
Requirements are within the comments of my attempted .gitignore file:
# Blacklist everything
*
# Whitelist directories of interest and their contents
# stage files in directory A/ recursively
!A/
!A/*
# stage files in directory B/B1/ recursively (without staging files in B/)
!B/B1/
!B/B1/**
# Whitelist files of interest
# stage only the .md files (not .txt files)
!*.md
How to write a .gitignore file that whitelists two directories?
The above gitignore file is based on .gitignore ignoring whitelisted folder
Here is the directory I tested .gitignore on:
$ find A B C
A
A/a.md
A/a.txt
A/A1
A/A1/a1.md
A/A1/a1.txt
B
B/b.md
B/b.txt
B/B1
B/B1/b1.md
B/B1/b1.txt
C
C/c.md
Here is how I tested the .gitignore file:
$ find A B C #list all paths
$ git init
#test .gitignore:
$ git add . --dry-run #show what would be staged
#edit gitignore and test again
Expected output:
$ git add . --dry-run
add 'A/A1/a1.md
add 'A/a.md
add 'B/B1/b1.md
This .gitignore file whiteslists the directories A and B/B1, and excludes .txt files:
#exclude files and directories in top directory
/*
#include the A directory
!/A
#include the B directory
!/B
#exclude files and directories in B
/B/*
#include the B/B1 directory
!/B/B1
#ignore .txt files
*.txt
It is based on last example in http://git-scm.com/docs/gitignore
You can solve your problem with several .gitignore files:
# .gitignore
*
!.gitignore
!A/
!A/*
!B/
!B/*
!*.md
# A/.gitignore
!*
# B/.gitignore
!*
This is what I did, based on the information in the cross-referenced question and the directory setup in this question:
$ mkdir junk
$ cd junk
$ git init
Initialized empty Git repository in /Users/jleffler/soq/junk/.git/
$ mkdir -p A/A1 B/B1 C
$ > A.md
$ > A/a.md
$ > A/a.txt
$ > A/A1/a1.md
$ > A/A1/a1.txt
$ > B/b.md
$ > B/b.txt
$ > B/B1/b1.md
$ > B/B1/b1.txt
$ > C/c.md
$ cat > .gitignore
*
!A/
!A/**
!B/
!B/**
!*.md
$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
A.md
A/
B/
nothing added to commit but untracked files present (use "git add" to track)
$ git add A.md A B
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: A.md
new file: A/A1/a1.md
new file: A/A1/a1.txt
new file: A/a.md
new file: A/a.txt
new file: B/B1/b1.md
new file: B/B1/b1.txt
new file: B/b.md
new file: B/b.txt
$
After adding A
and B
, all the files within are waiting to be added. Note that the .gitignore
file contains the directories (the trailing slash is not mandatory, AFAICT), and then the names !A/**
. The double star is key to the recursive search.
I used git reset
(having never actually made a commit), and jiggered with .gitignore
. I'm not clear that the goals are self-consistent at the moment. However, this modified .gitignore
file:
*
!A/
#!A/**.md
!B
!B/B1
#!B/B1/**.md
!*.md
B/b.md
plus git add A.md A B
yields:
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: A.md
new file: A/a.md
new file: B/B1/b1.md
$
You should be able to play with variations on the themes shown to get the result you desire. The !*.md
line tracks all .md
files. The B/b.md
line ignores B/b.md
, of course. The .md
file in C
is ignored because C is blacklisted (via the *
).