It's not completely impossible to do this, but it goes against the way Git is designed, which makes it difficult.
The fundamental issue here is that Git is all about commits rather than files. A commit does contain files—in fact, each commit has a complete snapshot of every file1—and when you use Git as a transport mechanism, it transports whole commits. But a commit is also the unit of tracking; each commit normally has a link to one parent commit; and following these links is what gets you the history. In other words, the commits are the history, and having a file in a commit means that the file will be tracked.2
Ultimately, then, the two goals of having the file be untracked, yet still transported ("uploaded"), conflict with each other. To be transported, the file must be in a commit. If the file is in the commit, the file will be tracked the moment that commit gets checked-out.
To make all of this work, you would need to commit the file and transport the commit, then either forget the commit while keeping the file somewhere (git reset
can do this), or else live with the commit existing and thus having the file tracked. When you want to update the file, you could make a new commit that has the side effect of discarding the old commit—e.g., using git commit --amend
—and then send the new commit. But since the commit is a complete snapshot, and commits are history, discarding the old commit means discarding a piece of history. That's only OK if the only things in the commit are the PDFs and UML diagrams.
There is also a hybrid process: have one chain of commits that grows normally (normal history) that lacks the PDF and UML files, and a separate single, parentless commit—in the same or some other repository, but for the purpose of this answer, assume "same repository"—that stores the PDFs and UML diagrams only. To update the single-commit files, discard the old single parentless commit, creating a new single parentless commit. You can then have your Git send to some other Git both the normal history and the current single commit. You then have to arrange for the other Git to git checkout
the normal history and extract the PDF-and-UML files into the work-tree of that other Git's repository, without putting those into the index.
Either of these methods—the one with a tricky commit-and-git reset
, or the hybrid in which you keep a single root commit with the PDFs and UML files—requires a lot of fancy support on the server end. This is not, as far as I know, available via GitHub. If you control the server, it's always possible to write your own code to do it.
1More precisely, a commit has a snapshot of every file that is in the commit. But putting it like this makes it an obvious tautology: the commit contains that which the commit contains.
To see what's in any particular commit, run:
git ls-tree -r <hash-or-other-specifier>
2The precise definition of a tracked file is that it is any file that is in the index. This requires getting into what the index is; but we can note, here, without going into detail, that the index is populated from a commit. This means that if commit 1234567...
stores file README
, anything that extracts the commit leaves README
in the index, so that it's tracked.