Asked  6 Months ago    Answers:  5   Viewed   27 times

I am using git on a relatively small project and I find that zipping the .git directory's contents might be a fine way to back up the project. But this is kind of weird because, when I restore, the first thing I need to do is git reset --hard.

Are there any problems with backing up a git repo this way? Also, is there any better way to do it (e.g., a portable git format or something similar?)?



I started hacking away a bit on Yar's script and the result is on github, including man pages and install script:


git clone ""
cd git-backup
sudo ./

Welcoming all suggestions and pull request on github.

#!/usr/bin/env ruby
# For documentation please sea man git-backup(1)
# - make it a class rather than a function
# - check the standard format of git warnings to be conform
# - do better checking for git repo than calling git status
# - if multiple entries found in config file, specify which file
# - make it work with submodules
# - propose to make backup directory if it does not exists
# - depth feature in git config (eg. only keep 3 backups for a repo - like rotate...)

# allow calling from other scripts
def git_backup

# constants:
git_dir_name    = '.git'          # just to avoid magic "strings"
filename_suffix = ".git.bundle"   # will be added to the filename of the created backup

# Test if we are inside a git repo
`git status 2>&1`

if $?.exitstatus != 0

   puts 'fatal: Not a git repository: .git or at least cannot get zero exit status from "git status"'
   exit 2

else # git status success

   until        File::directory?( Dir.pwd + '/' + git_dir_name )             
            or  File::directory?( Dir.pwd                      ) == '/'

         Dir.chdir( '..' )

   unless File::directory?( Dir.pwd + '/.git' )

      raise( 'fatal: Directory still not a git repo: ' + Dir.pwd )



# git-config --get of version 1.7.10 does:
# if the key does not exist git config exits with 1
# if the key exists twice in the same file   with 2
# if the key exists exactly once             with 0
# if the key does not exist       , an empty string is send to stdin
# if the key exists multiple times, the last value  is send to stdin
# if exaclty one key is found once, it's value      is send to stdin

# get the setting for the backup directory
# ----------------------------------------

directory = `git config --get`

# git config adds a newline, so remove it

# check exit status of git config
case $?.exitstatus

   when 1 : directory = Dir.pwd[ /(.+)/[^/]+/, 1]

            puts 'Warning: Could not find in your git config file. Please set it. See "man git config" for more details on git configuration files. Defaulting to the same directroy your git repo is in: ' + directory

   when 2 : puts 'Warning: Multiple entries of found in your git config file. Will use the last one: ' + directory

   else     unless $?.exitstatus == 0 then raise( 'fatal: unknown exit status from git-config: ' + $?.exitstatus ) end


# verify directory exists
unless File::directory?( directory )

   raise( 'fatal: backup directory does not exists: ' + directory )


# The date and time prefix
# ------------------------

prefix           = ''
prefix_date      = '%F'       ) + ' - ' # %F = YYYY-MM-DD
prefix_time      = '%H:%M:%S' ) + ' - '
add_date_default = true
add_time_default = false

prefix += prefix_date if git_config_bool( 'backup.prefix-date', add_date_default )
prefix += prefix_time if git_config_bool( 'backup.prefix-time', add_time_default )

# default bundle name is the name of the repo
bundle_name = Dir.pwd.split('/').last

# set the name of the file to the first command line argument if given
bundle_name = ARGV[0] if( ARGV[0] )

bundle_name = File::join( directory, prefix + bundle_name + filename_suffix )

puts "Backing up to bundle #{bundle_name.inspect}"

# git bundle will print it's own error messages if it fails
`git bundle create #{bundle_name.inspect} --all --remotes`

end # def git_backup

# helper function to call git config to retrieve a boolean setting
def git_config_bool( option, default_value )

   # get the setting for the prefix-time from git config
   config_value = `git config --get #{option.inspect}`

   # check exit status of git config
   case $?.exitstatus

      # when not set take default
      when 1 : return default_value

      when 0 : return true unless config_value =~ /(false|no|0)/i

      when 2 : puts 'Warning: Multiple entries of #{option.inspect} found in your git config file. Will use the last one: ' + config_value
               return true unless config_value =~ /(false|no|0)/i

      else     raise( 'fatal: unknown exit status from git-config: ' + $?.exitstatus )


# function needs to be called if we are not included in another script
git_backup if __FILE__ == $0
Tuesday, June 1, 2021
answered 6 Months ago

To create the mirror:

git clone --mirror git://

To update:

cd project.git
git remote update

To update without changing the current directory:

git --git-dir project.git remote update
Tuesday, June 1, 2021
answered 6 Months ago

If you have access to a shared directory, you can (see git clone and git remote):

git clone --bare /path/to/your/laptop/repo /shared/path/to/desktop/repo.git
git remote add desktop  /shared/path/to/desktop/repo.git

That will create a bare repo, referenced in your local repo as "desktop".
Since it is bare, you can push to it (as well as pull from it if needed)

git push desktop

As the ProGit book mentions, git does support the file protocol:

The most basic is the Local protocol, in which the remote repository is in another directory on disk.
This is often used if everyone on your team has access to a shared filesystem such as an NFS mount, or in the less likely case that everyone logs in to the same computer.

Saturday, June 12, 2021
answered 6 Months ago

You can use git-sync

apiVersion: apps/v1
kind: StatefulSet
  name: git-sync-test
      app: git-sync-test
  serviceName: "git-sync-test"
  replicas: 1
        app: git-sync-test
      - name: git-sync-test
        image: <your-main-image>
        - name: service
          mountPath: /var/magic
      - name: git-sync
        imagePullPolicy: Always
        - name: service
          mountPath: /magic
        - name: git-secret
          mountPath: /etc/git-secret
        - name: GIT_SYNC_REPO
          value: <repo-path-you-want-to-clone>
        - name: GIT_SYNC_BRANCH
          value: <repo-branch>
        - name: GIT_SYNC_ROOT
          value: /magic
        - name: GIT_SYNC_DEST
          value: <path-where-you-want-to-clone>
        - name: GIT_SYNC_PERMISSIONS
          value: "0777"
        - name: GIT_SYNC_ONE_TIME
          value: "true"
        - name: GIT_SYNC_SSH
          value: "true"
          runAsUser: 0
      - name: service
        emptyDir: {}
      - name: git-secret
          defaultMode: 256
          secretName: git-creds # your-ssh-key

For more details check this link.

Wednesday, August 11, 2021
answered 4 Months ago

I think the clone --mirror approach is worth looking back at. If you want to recover a past position of a branch which was force-pushed, just have a look at the reflogs. To be absolutely sure about this, you can set gc.pruneExpire to never, and the same for gc.reflogExpireUnreachable, so that reflogs and unreachable objects will never be removed. That ought to cover you. Important note: reflogs are by default disabled in bare repositories. You can enable them by setting core.logAllRefUpdates.

Do note that the reflogs in the pushed-to repository will contain records of any forced pushes that happen. If you want to be even more sure about this, you could even write an update hook that detects incoming forced updates and records them somewhere special, perhaps by creating a ref, something like refs/backups/mybranch-{n}.

And really, there's nothing wrong with some branches being rebased frequently, as long as it's in a well-defined way, so that no one is caught off guard. The pu branch in git.git is a perfect example of this.

Sunday, October 3, 2021
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :