Skip to content

Instantly share code, notes, and snippets.

@JohnArchieMckown
Last active September 10, 2015 13:19
Show Gist options
  • Save JohnArchieMckown/9a1413bb419ffcc80912 to your computer and use it in GitHub Desktop.
Save JohnArchieMckown/9a1413bb419ffcc80912 to your computer and use it in GitHub Desktop.
How to use git to store binary data, such as a "release level" containing executables & other non-textual files
On Thu, 10 Sep 2015 00:23:09 -0700 (PDT)
[email protected] wrote:
> I'm very new to VCS and git, so I have some difficulties to use them.
>
> I'd like to use git for my embedded projects. I consider a must have
> feature the possibility to retrieve the binary files of an old
> release. In this way, I can reprogram a real device with EXACTLY the
> same binary after some years since the release.
>
> I understood it's better to not add binary files to the repository.
> Indeed I don't need to track binary files for every commit. The only
> thing I need is to add additional non-tracked/ignored files
> (binaries) to a few commits, usually tags for production releases.
>
>
> How to reach this goal?
The simplest solution I can think of, which does not involve any tools
outside of Git (well, almost), is using the lesser-known fact Git's
object database is able to store arbitrary data -- not necessarily
bound to a commit.
The basic idea is like this: once the release build is done, you
1) Archive the necessary binary files (that's really platform-dependent:
on Windows, I'd use plain zip, on POSIX systems, tar + gz or tar + xz
or 7zip is supposedly better; in either case it's up to you).
This is needed to provide a single file.
2) Put it into the object database:
$ git hash-object -w path/to/that/archive_file
This command will print the SHA-1 name of the file's contents,
and by that time, those contents will already be in the Git
database in the form of a so-called "blob".
3) Tag this object:
$ git tag rel-1.2.3-bin that_sha1_name_from_step2
---
(self) combine steps (Linux only?):
git tag rel-1.2.3-bin $(git hash-object -w path/to/that/archive_file)
---
You might want to add "-a" to this invocation to create an
annotated tag instead.
4) Push the tag to the "upstream" repo:
$ git push origin rel-1.2.3-bin
This command will push the tag and the blob it references to the
"upstream" repository.
At a later point in time you will be able to get the contents of
your file back using
$ git show rel-1.2.3-bin >path/to/archive_file
that is, via simple output redirection.
The downside of this approach is that you're going to have two tags per
each release: one for "the source" and another one for "the binary".
Two other possibilities:
* Just add the binary files to make a release commit and then
immediately
$ git rm --cached all those files
afterwards.
I dislike this approach precisely because it mixes the sources and the
binaries, but pick whatever works for you. If this would be the
easiest path, just take it.
* Have a separate branch for binaries.
After the release, save your binaries somewhere, check out that
branch, copy your binaries over, add/remove changes, commit.
The downside is that if the size of the tree in your normal
("sources") branch is of hefty size, checkout to the "binary" branch
and back will take noticeable time. YMMV, of course.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment