Search code examples
gitversion-control

How to prevent your internal project documentation from being pushed to remote repo while it still needs to be tracked locally?


I have gone through similar questions on stackoverflow but none of them quite satisfy the need. Using gitignore won't let me track changes of the documentation. Using submodules, again won't be part of the main repo, and would have to be commited separately.

Another similar question might be if it is at all possible using git to exclude some files/folders only when you push.

To make it more clear, I have a project say project

project

|_codefolder1/

|_codefolder2/

|_codefile1

|_etc

|_docs/

what I want is not to push docs/ to production or testing servers at all. But I still want to keep changing and tracking the documentation as it is important to tie specific documentation to a specific version of the product.

Are there any workarounds or am I missing some built-in functionality of git?


Solution

  • You don't.

    Another similar question might be if it is at all possible using git to exclude some files/folders only when you push.

    You can't.

    When you run git push, that operation does not send files to the other Git repository. That operation sends commits to the other repository.

    Each commit holds a full snapshot of every file, like an archive (tar or rar or winzip or whatever). More precisely, each commit holds all the files that it holds: it either has some file—docs/foo.txt—or it does not. (Commits do not contain folders, only files: the files may have names that have forward slashes in them, and Git knows that the OS requires that storing a file named docs/foo.txt requires that Git make a folder named docs and then store a file named foo.txt in that folder, but as far as the commit goes, it's just a file named docs/foo.txt.)

    A file is tracked if it is in Git's index. It is untracked if it is not in Git's index. When you select a different commit to check out, Git:

    • removes, from its index and your working tree, the tracked files that came out of the current commit;
    • installs, into its index and your working tree, the files from the newly selected commit: those are now the tracked files; and
    • makes the newly selected commit (and branch name if you selected it via a branch name) the current commit (and branch name).

    When you build a new commit, Git takes all the tracked files—all the copies that are in its index—and uses that to make the archive for the new commit. The set of files in that new commit is thus exactly the files that are tracked, as they appear in Git's index (not necessarily as they appear in your working tree: if you did not git add some updated copy, the index copy is the old version).

    So if the files are committed, they're tracked. If they're not tracked, they're not committed. The git push operation pushes the commits. That's all there is in Git: that's all you get.

    (This is why, e.g., submodules exist, and systems like Google's , and so on.)