Created
March 3, 2019 10:33
-
-
Save VarunBarad/c291e98dd426b0da1322171290d7bbd0 to your computer and use it in GitHub Desktop.
Script to create a single-file backup of a git repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import os | |
import sys | |
import re | |
import shutil | |
from git import Repo | |
from zipfile import ZipFile | |
def create_backup_zip(directory_to_backup): | |
parent_directory, directory_name = os.path.split(directory_to_backup) | |
repository = Repo(directory_to_backup) | |
git_handle = repository.git | |
git_bundle_file_name = os.path.join(parent_directory, (directory_name + '.bundle')) | |
git_handle.bundle('create', git_bundle_file_name, '--all') | |
pattern_for_untracked_files_flag = re.compile(r'^\?+$') | |
non_staged_files_raw_output = git_handle.status('--porcelain') | |
if len(non_staged_files_raw_output.strip()) > 0: | |
non_staged_files = list(filter( | |
lambda x: pattern_for_untracked_files_flag.match(x[0]) is None, | |
list(map(lambda _: _.strip().split(), non_staged_files_raw_output.split(os.linesep))) | |
)) | |
else: | |
non_staged_files = [] | |
if len(non_staged_files) > 0: | |
git_handle.stash('push', '-m', 'git-backup-stash') | |
stashes = git_handle.stash('list').strip() | |
stash_list = stashes.split(os.linesep) | |
patch_files = [] | |
if (len(stashes) > 0) and (len(stash_list) > 0): | |
patch_files_directory = os.path.join(parent_directory, 'patch-files') | |
os.makedirs(patch_files_directory, exist_ok=True) | |
for stash in stash_list: | |
stash_name = stash.split(': ')[0] | |
stash_branch_name = stash.split(': ')[1].split()[1] | |
stash_message = ': '.join(stash.split(': ')[2:]) | |
patch_file_name = ':'.join([stash_name, stash_branch_name, stash_message]) + '.txt' | |
patch_file_path = os.path.join(patch_files_directory, patch_file_name) | |
patch_contents = git_handle.stash('show', '-p', stash_name) | |
with open(patch_file_path, 'x') as f: | |
f.write(patch_contents) | |
patch_files.append(patch_file_path) | |
zip_file_name = directory_name + '.zip' | |
zip_file_path = os.path.join(parent_directory, zip_file_name) | |
with ZipFile(zip_file_path, 'x') as z: | |
z.write(git_bundle_file_name, arcname=os.path.split(git_bundle_file_name)[1]) | |
for patch_file in patch_files: | |
z.write(patch_file, arcname=os.path.join('patch-files', os.path.split(patch_file)[1])) | |
os.remove(git_bundle_file_name) | |
if len(patch_files) > 0: | |
shutil.rmtree(patch_files_directory) | |
print(zip_file_name + ' created') | |
if __name__ == "__main__": | |
arguments = sys.argv[1:] | |
if len(arguments) == 0: | |
directory_to_backup = os.getcwd() | |
else: | |
directory_to_backup = arguments[0] | |
directory_to_backup = os.path.abspath(directory_to_backup) | |
git_directory = os.path.join(directory_to_backup, '.git') | |
if os.path.exists(git_directory) and os.path.isdir(git_directory): | |
create_backup_zip(directory_to_backup) | |
else: | |
print(directory_to_backup + ' is not a git repository') |
@flandersen I guess bare repos won't have any stashes. In that case all you need should be handled by git bundle
@VarunBarad Thank you! I have tested git-bundle and it works fine.
If you are interested, here is the script I came up with which fits my purpose:
https://gist.github.com/flandersen/6d33c609de80247c9059bf8c3e2ade05
Thanks @flandersen
I really liked how you have put the documentation at the top of the script in comments 💯
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@VarunBarad I want to backup my repos on my server which are created the following:
git init --bare <directory>