How is it possible to export all commits into ZIP files (containing all files, not only patch/diff):
myproject-commit1-67d91ab.zip
myproject-commit2-9283acd.zip
myproject-commit3-c57daa6.zip
...
or into directories:
myproject-commit1-67d91ab/
myproject-commit2-9283acd/
myproject-commit3-c57daa6/
?
I was thinking about commands like:
git archive --format zip --output myproject-commit3.zip c57daa6
from How do I export a specific commit with git-archive?, but how to get all commits?
Notes:
the goal is to do an export of all files of each commit, so that I can have access to them even if I don't have git
on the machine
the answer from How can I export Git change sets from one repository to another via sneaker net (external files)? creates a .bundle
file, but it seems impossible to access it without git
, so it's not what I'm looking for
this nearly works:
for ((i = 0;; ++i)); do git checkout master~$i || break; tar czf ../myproject-commit$i.tgz .; done
but it also archives all the files in the current directory which are not
git add
ed to the repo... How to avoid this problem?
You can't, except by the methods you are already thinking about.
Specifically, to turn every commit into a zip archive (one separate archive per commit), simply iterate over every commit, turning each one into a zip archive.
Your method for iterating simply needs to walk all possible commits, rather than walking only all first-parents of the master
branch, and you must use git archive
on each such commit. Hence:
git rev-list --all |
while read hash; do git archive ...options... $hash
done
The command git rev-list --all
tells Git to print out every reachable commit hash ID, in some order. To change the order, use the various sorting options available to both git rev-list
and git log
(e.g., --author-date-order
or --topo-order
).
If you don't want every commit—if you want instead only first-parents of master—you can still do this with git rev-list
:
git rev-list --first-parent master | ...
Here, since Git is walking only first-parents starting from whichever commit master
identifies, the hash IDs will be output in what Git considers forward order, i.e., backwards across the branch's first-parents:
...--o--o--o--o--o--o------o <-- master
\ \ /
\ X--X--...X <-- somebranch
\ /
X--X----X--X <-- anotherbranch
None of the X
commits will appear since they are not on the first-parent lineage. (Without --first-parent
, since all the commits on somebranch
, and all but the last one on anotherbranch
, are also on master
, you would get all the X
commits.)
[Basj adds the following, which appears to be bash-specific due to $((i=i+1))
:] Edit: this is a ready to use command to do it as described in the question:
git rev-list --all --reverse | while read hash; do git archive --format zip --output ../myproject-commit$((i=i+1))-$hash.zip $hash; done
[torek feels the need to add :-) : Note that the above enumerates commits sequentially, even if this is not an invertible mapping.]