Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Backup a github repository from Windows. Assumes B2 command lines tools, python, and 7ZIP are installed. Script requires some variables (B2 account, etc) to filled in.
@echo off
REM Script to backup git repo to Backblaze B2
REM Set bucket, local directory, password and account to use for the backup.
:: NOTE: might want to import these from the outer environment
:: rather than setting them internally
REM set localDir=%LOCALDIR%
REM set zipPassword=%GIT_ZIP_PASSWORD%
REM set b2Account=%B2_ACCOUNT_ID%
REM set b2Key=%B2_ACCOUNT_KEY%
REM *************************************************
REM * Set these variables to configure the script
REM *************************************************
set localDir=tempGitToBackblazeB2Backup
set b2Path=gitBackups
set zipPassword=securityThroughObscurityIsAKnownSecurityRisk
set b2Bucket=b2BucketNameGoesHere
set b2Account=7dab0707
set b2Key=aabb44cc34590918af1254e5568d
REM To restore this repo in the future, download it from B2, extract it and then use this command:
REM cd old-repository.git
REM git push --mirror
REM *************************************************
REM *************************************************
REM Initial setup of spacers & errcode
REM NOTE! Some editors will turn the TAB character in the next line into spaces,
REM which will be treated as white space by the ECHO cmd built-in, and that
REM will spoil the indents of some error and help messages.
set "tab= "
set 2tb=%tab%%tab%
set 3tb=%2tb%%tab%
set err=0
REM setup for SSH
REM Installing and getting SSH up is beyond the scope
REM of this script. If SSH/GIT is up and working, and
REM GIT is correctly working with it, then switch
REM over to using SSH by setting useSSH to YES
set useSSH=no
:: =============================================================== ::
:: These variables need to be set by the script user
:: Verify that these are all configured
:: =============================================================== ::
if [%b2Bucket%] == [] (
set err=404
echo %tab% Backblaze B2 bucket (b2Bucket) variable is unset.
if [%b2Account%] == [] (
set err=404
echo %tab% Backblaze account ID (b2Account) variable is unset.
if [%b2Key%] == [] (
set err=404
echo %tab% Backblaze account key (b2Key) variable is unset.
if not %err% equ 0 (
:: ============================================================== ::
:: check the arguments for validity
:: ============================================================== ::
REM special case: help request
if /I [%1] == [/h] (
REM empty arguments?
if [%2] == [] (
set err=102
REM will exit
if [%1] == [] (
set err=101
REM will exit
REM too many arguments?
if not [%3] == [] (
set err=103
REM will exit
REM set zip command tool. It is run as:
REM zipExe zipCmd zipArg [ArchiveFile] [ArchiveDirectory]
REM if there is a password configured, use it, otherwise, don't
set passParam%=
if NOT [%zipPassword%] == [""] (
set passParam=-p%zipPassword%
set zipExe=7z
set zipCmd=a
set zipArg=-mx9 -t7z -ms=on -r -y %passParam%
REM Setup repository to name - repo
set repoUser=%1%
set repoName=%2%
set repo=%repoUser%/%repoName%
REM kludge to get locale-independent timestamp
pushd "%temp%"
makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul
for /f "tokens=3-7" %%a in ('find /i "makecab"^<~.rpt') do (
set "current-date=%%e_%%b_%%c"
set "initial-time=%%d"
set "weekday=%%a"
REM colon is an invalid file-character, so replace with h-m-s
echo %initial-time% > ~.tml
for /f "tokens=1-3 delims=:" %%q in ( ~.tml ) do (
set "init_time=%%qh%%rm%%ss"
REM remove any spaces
set current-time=%init_time: =%
set timestamp=%current-date%_%current-time%
REM echo %timestamp%
REM Create the backup directory
if not exist %localDir% (
mkdir %localDir%
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") creating directory %localDir%
set err=110
echo %tab% Backing up %repo% ...
REM if SSH has been enabled, yay. If not ...
if /I [%useSSH%] ==[YES] (
) else (
set gitURL=
REM create a specific timestamped directory
set repoDirectory=%localDir%\%repoName%.%timestamp%.git
REM name of archive
set repo7z=%repoName%.%timestamp%.7z
echo %tab% cloning %gitURL%%repo% to %repoDirectory% ...
git clone --mirror %gitURL%%repo% %repoDirectory% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") cloning " %repository%
set err=111
echo %tab% ... clone successful
echo %tab% Compressing %repoDirectory% to %repo7z% ...
%zipExe% %zipCmd% %zipArg% %repo7z% %repoDirectory% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") zipping "%localDir%\%repository%.%timestamp%.git
set err=112
echo %tab% ... compression successful
echo %tab% Uploading to Backblaze B2 ...
b2 authorize-account %b2Account% %b2Key% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") running b2 authorize-account %b2Account% %b2Key%
set err=121
REM suppress the returned information from B2 UPLOAD-FILE and simply report the errorlevel if not 0
b2 upload-file --noProgress %b2Bucket% %repo7z% %b2Path%/%repo7z% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") running b2 upload-file --noProgress %b2Bucket% %repo7z% %b2Path%/%repo7z%
set err=122
echo %tab% ... upload successful
echo %tab% Starting cleanup
rmdir /s /q %localDir% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") removing %localDir%
set err=131
del %repo7z% > nul 2>&1
if %ERRORLEVEL% neq 0 (
echo "Error (" %ERRORLEVEL% ") removing %repo7z%
set err=131
echo %tab% ... cleanup successful
echo %tab% Successfully backed up %repo% to %b2Bucket%/%b2Path%/%repo7z%
exit /b %err%
echo %tab% Usage: %~nx0 <git-accountname> <git-repo-name>
echo %2tb% example: %~nx0 henryHiggins elizaSpeechUpgrade
echo %tab% Please note the script has several variables that
echo %tab% must be set by the user.
REM echo %tab%
exit /b %err%
REM echo %tab%
echo %tab% Unexpected or missing arguments!
echo %tab%%tab% Expected: %~nx0 [gituser] [getrepo]
echo %tab%%tab% Why not try %~nx0 /h instead?
exit /b %err%
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="">
<title>Backing up a Github repository to Backblaze B2 from the Windows Command Line</title>
<link href=",400i,600,600i|IBM+Plex+Serif:400,400i,600,600i" rel="stylesheet"/>
h1 {
color: indigo;
text-align: center;
font-variant: small-caps;
line-height: 110%;
h1 tt {
color: darkgreen;
font-size: 80%;
font-family: "IBM Plex Mono", "Consolas", "Lucida Console", monospace;
font-variant: normal;
.primary {
margin: 1em 10px 2em 10px;
font-family: "IBM Plex Serif", serif;
font-size: 1em;
line-height: 115%;
margin: 1em 9px 3em 10px;
tt {
font-size: 80%;
font-family: "IBM Plex Mono", "Consolas", "Lucida Console", monospace;
color: darkgreen;
font-weight: bolder;
p {
text-indent: 0;
margin: .75em 0 0 0;
dl {
margin: 0 4% 0 5%;
dt {
margin: .75em;
dt tt {
color: darkslateblue;
dd p:first-child {
margin: 0;
dd blockquote {
margin-top: 0;
margin-bottom: 0;
dd blockquote tt {
font-family: monospace;
font-size: 80%;
color: darkgreen;
<body class="primary">
<h1>Backing up a Github repository to Backblaze B2<br/> From Windows<br/> using <tt>7Zip</tt>, the B2 Command lines Tools, and <tt>Git</tt><br/> from a command batch file</h1>
<p>Recently, we’ve seen interest in backing up the entirety of a <a href="">Github</a> repository and — because they are large — stashing those repositories in secure cloud storage. This is a quick and simplistic batch file to compress and backup a repository.</p>
<div style="margin: .5em 5% .5em 5%">
<div style="margin: .5em 5% .5em 5%">
<tt>github2b2.bat <i>&lt;RepositoryOwner&gt; &lt;RepositoryName&gt;</i></tt>
<dd>The GitHub account owner</dd>
<dd>Name of the repository to back up</dd>
<p>The repository will be backed up to a (hard-coded, see below) B2 bucket with the name and a current timestamp.</p>
<p>A few variables in the script need to be set explicitly by the user. The affected lines are:</p>
<dt><tt>set b2Account=7dab0707</tt></dt>
<dd>B2 AccountID</dd>
<dt><tt>set b2Key=aabb44cc34590918af1254e5568d</tt></dt>
<dd>B2 AuthorizationSecretKey</dd>
<dt><tt>set b2Bucket=b2BucketNameGoesHere</tt></dt>
<dd>This is the bucket in which the repository goes</dd>
<dt><tt>set localDir=tempGitToBackblazeB2Backup</tt></dt>
<dd>The script will use this as a local directory to produce the archive; it will not be reflected in the archive tree (it is used only as a scratch working area)</dd>
<dt><tt>set b2Path=gitBackups</tt></dt>
<dd>Path within the bucket, thus the repository backup will be: <tt>&lt;bucket&gt;/&lt;path&gt;/reponame.timestamp.7z</tt></dd>
<dt><tt>set zipPassword=securityThroughObscurityIsAKnownSecurityRisk</tt></dt>
<dd>Password for 7zip file. If this is set to the empty string, the archive will not have a password.</dd>
<p>Since these are timestamped snapshots, these are compressed in solid-block mode (that is, the archives cannot be updated later), and 7zip is configured to use maximum compression. Additionally, if there is a password, it will be encrypted with AES-256 (per the 7z documentation).</p>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.