George Garside Blog

A place of many ramblings about macOS and development. If you find something useful on here, it's probably an accident.

git.day/7 • See all at git.day

Diffing files is a very common operation in Git, leading many to believe Git commits are diffs between state, requiring one to go back to the first commit to recreate a file accurately. This is untrue as commits are snapshots of the state of the repo at any point.

The same thought process can be applied to the index. The index needs to keep track of changes to files, which means the scope of the files needs to be able to be controlled. Git has the concept of tracked and untracked files. Only tracked files, as the name suggests, are tracked by Git for changes. New files added to a repository must be tracked or are otherwise ignored.

$ echo "Foo" > README.md
$ git diff
# no outputCode language: Shell Session (shell)

This means new files must be git add before any changes will be tracked by Git and made available for commands like git diff. However, git add on an untracked file not only adds the addition of the file to the index, but as with any tracked file being add, the contents is added too. This may not be desired at the current point in time.

$ git add README.md
$ git diff
# no outputCode language: Shell Session (shell)

To solve this problem, one can use git add --intent-to-add <file> and tell Git that a file will be added and tracked, but the contents of the file should not be added to the index yet.

$ git reset README.md  # undo add
$ git add --intent-to-add README.md
$ git diff
# diff!
Code language: Shell Session (shell)

The diff produced says ‘new file’ and is comparing against /dev/null i.e. emptiness. The entire contents of the file is a change yet to be added to the index.

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1234567
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+FooCode language: Diff (diff)

This is also explained in a git status, where previously it shows a file found in the working directory but not tracked by Git.

Untracked files:
    README.mdCode language: plaintext (plaintext)

The file is added to the list of changes like any change to a tracked file, except instead of ‘modified’, the change is explained as ‘new file’, the same as git diff:

Changes not staged for commit:
    new file:  README.mdCode language: plaintext (plaintext)

This is especially helpful when working in a repository with lots of untracked files, such as crafting a useful initial commit for a new repository on an existing directory, or crafting smaller commits for a large change creating lots of untracked files at once.

Leave a Reply

No comments