Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export all commits into ZIP files or directories

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 added to the repo... How to avoid this problem?

like image 900
Basj Avatar asked Oct 30 '25 13:10

Basj


1 Answers

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.]

like image 182
torek Avatar answered Nov 01 '25 13:11

torek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!