Reputation: 1220
If I have a git repository that has both source code and other types of file, such slides, binary, etc. I want git to just version control the text file ( such as source code ). For other file types (binaries, for example), I just want to store one copy in the git repository, i.e. I want git to overwrite the file whenever I update it. I don't want to store multiple version for other types of file as they may be very large. Is there a way to config git for that purpose ? I run my own git host.
Thanks in advance!
Upvotes: 5
Views: 1543
Reputation: 17674
add
and commit
all files you want to store in the repo once in a separate commit.
first commit should be of a file you want to keep track of (ie the text file).
each time you change a file which you want to keep track of, you make a new commit like you normally do.
each time you change a file which you want to be stored once, you make a new commit and rebase
/fixup
the commit to the commit that added the binaries.
here is the idea in practice:
$ ls
banana.pdf bar.bin foo.txt mew.ppt
$ git status -s
?? banana.pdf
?? bar.bin
?? foo.txt
?? mew.ppt
add files - first the files to keep track of then all the binaries
$ git add foo.txt
$ git commit -m "foo text file"
$ git tag "root" HEAD # easy access to the first commit
$ git add banana.pdf bar.bin mew.ppt
$ git commit -m "binaries"
make changes and commits
$ echo "ohai, I'm a change :D" >> foo.txt
$ git add foo.txt
$ git commit -m "foo changed"
$ echo "ohai, I'm a banana" | hexdump >> banana.pdf
$ git add banana.pdf
$ git commit -m "fixup! binaries"
lets look at what we have
$ git log --oneline
42c09bd fixup! binaries # this will be merge with
a9b1853 foo changed
8899046 binaries # this - same commit message!
7c8ae05 foo text file # this is also the 'root' tag
now rebase the commits to fixup the commits for the binaries
$ git rebase --autosquash -i root # everything will be ready for us
pick 8899046 binaries
fixup 42c09bd fixup! binaries # notice this :)
pick a9b1853 foo changed
:wq # vim save and quit
$ git log --oneline # lets look at what we end up with
41e1f09 foo changed
50adb90 binaries
7c8ae05 foo text file
it is very important to mark the new commit for the "non-tracked" file as
git commit -m "fixup! <same message as the commit to merge with>"
in our case the original message of the commit that added the 'banana.pdf' was binaries
so the commit message for the commit that changed any of the binaries should be fixup! binaries
(as it is in the example)
if you do not name the commit that way then --autosquash
cannot help you, and you have to manually move the line of the commit you want to change under the commit you want it to be merged with, and replace 'pick' with 'fixup', for example (continuing from where we left):
$ echo "ohai, more changes" >> bar.bin
$ git add bar.bin
$ git commit -m "changed bar"
$ git log --oneline
bd36eb9 changed bar
41e1f09 foo changed
50adb90 binaries
7c8ae05 foo text file
$ git rebase -i root
pick 50adb90 binaries # you want this to merge with
pick 41e1f09 foo changed
pick bd36eb9 changed bar # this
so change it to
pick 50adb90 binaries
fixup bd36eb9 changed bar # under the line to be merged with and with 'fixup' instead of 'pick'
pick 41e1f09 foo changed
:wq # save and quit
$ git log --oneline # what we end up with
9f94cbe foo changed
886eebd binaries
7c8ae05 foo text file
done :)
if you want to go further you can automate this with a git hook. see
$ git help githooks
a pre-commit
hook would do the work for you with some tricks
Upvotes: 3
Reputation: 14101
Git, being a snapshot based VCS, with a cryptographically secure hash across the history, is not able to 'forget' an old version and replace it with a 'new' version of a file. This would break its crypto security.
Git is designed to be optimal for source code, and isn't optimal for binary files, but then neither are other VCS systems.
One solution is to ignore your binary files for the git repo, but create an alias for the git commit
that will detect the binary file change and replace a copy in your separate archive, assuming its that important.
Do remember that if your binary files do not change very often then git is efficient about first, not storing duplicates, and second compressing those files. You can also mark the files as --assume-unchanged
(i've not used it so check the manual) so that short-term changes are ignored.
Upvotes: 2