-
-
Save VarunBarad/c291e98dd426b0da1322171290d7bbd0 to your computer and use it in GitHub Desktop.
| #!/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 could not understand what you mean by "bare git repos". Can you please explain a bit more?
@VarunBarad I want to backup my repos on my server which are created the following:
git init --bare <directory>
The --bare flag creates a repository that doesn’t have a working directory, making it impossible to edit files and commit changes in that repository. You would create a bare repository to git push and git pull from, but never directly commit to it.
https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init
@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 💯
I want to backup my bare git repos and give it a try, but this script cannot handle those.