github.com/x-oss-byte/git-lfs@v2.5.2+incompatible/docs/spec.md (about) 1 # Git LFS Specification 2 3 This is a general guide for Git LFS clients. Typically it should be 4 implemented by a command line `git-lfs` tool, but the details may be useful 5 for other tools. 6 7 ## The Pointer 8 9 The core Git LFS idea is that instead of writing large blobs to a Git repository, 10 only a pointer file is written. 11 12 * Pointer files are text files which MUST contain only UTF-8 characters. 13 * Each line MUST be of the format `{key} {value}\n` (trailing unix newline). 14 * Only a single space character between `{key}` and `{value}`. 15 * Keys MUST only use the characters `[a-z] [0-9] . -`. 16 * The first key is _always_ `version`. 17 * Lines of key/value pairs MUST be sorted alphabetically in ascending order 18 (with the exception of `version`, which is always first). 19 * Values MUST NOT contain return or newline characters. 20 * Pointer files MUST be stored in Git with their executable bit matching that 21 of the replaced file. 22 23 An empty file is the pointer for an empty file. That is, empty files are 24 passed through LFS without any change. 25 26 The required keys are: 27 28 * `version` is a URL that identifies the pointer file spec. Parsers MUST use 29 simple string comparison on the version, without any URL parsing or 30 normalization. It is case sensitive, and %-encoding is discouraged. 31 * `oid` tracks the unique object id for the file, prefixed by its hashing 32 method: `{hash-method}:{hash}`. Currently, only `sha256` is supported. 33 * `size` is in bytes. 34 35 Example of a v1 text pointer: 36 37 ``` 38 version https://git-lfs.github.com/spec/v1 39 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 40 size 12345 41 (ending \n) 42 ``` 43 44 Blobs created with the pre-release version of the tool generated files with 45 a different version URL. Git LFS can read these files, but writes them using 46 the version URL above. 47 48 ``` 49 version https://hawser.github.com/spec/v1 50 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 51 size 12345 52 (ending \n) 53 ``` 54 55 For testing compliance of any tool generating its own pointer files, the 56 reference is this official Git LFS tool: 57 58 **NOTE:** exact pointer command behavior TBD! 59 60 * Tools that parse and regenerate pointer files MUST preserve keys that they 61 don't know or care about. 62 * Run the `pointer` command to generate a pointer file for the given local 63 file: 64 65 ``` 66 $ git lfs pointer --file=path/to/file 67 Git LFS pointer for path/to/file: 68 69 version https://git-lfs.github.com/spec/v1 70 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 71 size 12345 72 ``` 73 74 * Run `pointer` to compare the blob OID of a pointer file built by Git LFS with 75 a pointer built by another tool. 76 77 * Write the other implementation's pointer to "other/pointer/file": 78 79 ``` 80 $ git lfs pointer --file=path/to/file --pointer=other/pointer/file 81 Git LFS pointer for path/to/file: 82 83 version https://git-lfs.github.com/spec/v1 84 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 85 size 12345 86 87 Blob OID: 60c8d8ab2adcf57a391163a7eeb0cdb8bf348e44 88 89 Pointer from other/pointer/file 90 version https://git-lfs.github.com/spec/v1 91 oid sha256 4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 92 size 12345 93 94 Blob OID: 08e593eeaa1b6032e971684825b4b60517e0638d 95 96 Pointers do not match 97 ``` 98 99 * It can also read STDIN to get the other implementation's pointer: 100 101 ``` 102 $ cat other/pointer/file | git lfs pointer --file=path/to/file --stdin 103 Git LFS pointer for path/to/file: 104 105 version https://git-lfs.github.com/spec/v1 106 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 107 size 12345 108 109 Blob OID: 60c8d8ab2adcf57a391163a7eeb0cdb8bf348e44 110 111 Pointer from STDIN 112 version https://git-lfs.github.com/spec/v1 113 oid sha256 4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 114 size 12345 115 116 Blob OID: 08e593eeaa1b6032e971684825b4b60517e0638d 117 118 Pointers do not match 119 ``` 120 121 ## Intercepting Git 122 123 Git LFS uses the `clean` and `smudge` filters to decide which files use it. The 124 global filters can be set up with `git lfs install`: 125 126 ``` 127 $ git lfs install 128 ``` 129 130 These filters ensure that large files aren't written into the repository proper, 131 instead being stored locally at `.git/lfs/objects/{OID-PATH}` (where `{OID-PATH}` 132 is a sharded filepath of the form `OID[0:2]/OID[2:4]/OID`), synchronized with 133 the Git LFS server as necessary. Here is a sample path to a file: 134 135 .git/lfs/objects/4d/7a/4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 136 137 The `clean` filter runs as files are added to repositories. Git sends the 138 content of the file being added as STDIN, and expects the content to write 139 to Git as STDOUT. 140 141 * Stream binary content from STDIN to a temp file, while calculating its SHA-256 142 signature. 143 * Atomically move the temp file to `.git/lfs/objects/{OID-PATH}` if it does not 144 exist, and the sha-256 signature of the contents matches the given OID. 145 * Delete the temp file. 146 * Write the pointer file to STDOUT. 147 148 Note that the `clean` filter does not push the file to the server. Use the 149 `git push` command to do that (lfs files are pushed before commits in a pre-push hook). 150 151 The `smudge` filter runs as files are being checked out from the Git repository 152 to the working directory. Git sends the content of the Git blob as STDIN, and 153 expects the content to write to the working directory as STDOUT. 154 155 * Read 100 bytes. 156 * If the content is ASCII and matches the pointer file format: 157 * Look for the file in `.git/lfs/objects/{OID-PATH}`. 158 * If it's not there, download it from the server. 159 * Write its contents to STDOUT 160 * Otherwise, simply pass the STDIN out through STDOUT. 161 162 The `.gitattributes` file controls when the filters run. Here's a sample file that 163 runs all mp3 and zip files through Git LFS: 164 165 ``` 166 $ cat .gitattributes 167 *.mp3 filter=lfs -text 168 *.zip filter=lfs -text 169 ``` 170 171 Use the `git lfs track` command to view and add to `.gitattributes`.