Могу ли я хранить папку.git вне файлов, которые я хочу отслеживать?

У меня есть необычная идея использовать git в качестве системы резервного копирования. Допустим, у меня есть каталог./backup/myfiles, и я хочу сделать резервную копию, используя git. Чтобы сохранить вещи в чистоте, я не хочу, чтобы в папке myfiles был каталог.git, поэтому я подумал, что могу создать./backup/git_repos/myfiles. Посмотрев на git docs, я попытался сделать это:

$ cd backup/myfiles
$ mkdir ../git_repos/myfiles
$ git --git-dir=../git_repos/myfiles init
Initialized empty Git repository in backup/git_repos/myfiles/
$ git --git-dir="../git_repos/myfiles/" add foo
fatal: pathspec 'foo' did not match any files

Вы можете увидеть сообщение об ошибке, которое я получил там. Что я делаю неправильно?

10 ответов

Решение
git --git-dir=../repo --work-tree=. add foo

Это будет делать то, что вы хотите, но, очевидно, будет отстой, когда вам нужно будет указать это с каждой командой git, которую вы когда-либо использовали.

Вы можете экспортировать GIT_WORK_TREE=. а также GIT_DIR=../backup и Git будет подбирать их в каждой команде. Это только позволит вам удобно работать в одном репозитории на оболочку.

Я бы предпочел использовать символическую ссылку на каталог.git в другом месте или создать символическую ссылку на каталог.git из основного каталога резервного копирования.

Вам просто нужно убедиться, что хранилище знает, где находится дерево работы, и наоборот.

Чтобы сообщить хранилищу, где находится рабочее дерево, установите значение конфигурации core.worktree, Чтобы сообщить рабочему дереву, где находится его каталог git, добавьте файл с именем.git (не папка!) И добавьте строку вроде

gitdir: /path/to/repo.git

Начиная с git 1.7.5 команда init изучила дополнительную опцию для этого.

Вы можете инициализировать новый отдельный репозиторий с помощью

git init --separate-git-dir /path/to/repo.git

Это инициализирует репозиторий git в отдельном каталоге и добавит файл.git в текущий каталог, который является рабочим каталогом нового репозитория.

Раньше до 1.7.5 вам приходилось использовать немного другие параметры и добавлять файл.git самостоятельно.

Чтобы инициализировать отдельный репозиторий, следующая команда связывает рабочее дерево с репозиторием:

git --git-dir=/path/to/repo.git --work-tree=. init && echo "gitdir: /path/to/repo.git" > .git

Ваш текущий каталог будет рабочим деревом, а git будет использовать репозиторий на /path/to/repo.git, Команда init автоматически установит core.worktree значение, указанное с помощью --git-dir параметр.

Вы могли бы даже добавить псевдоним для этого:

[alias]
    initexternal = !"f() { git --work-tree=. --git-dir=\"$1\" init && echo \"gitdir: $1\" >> .git; }; f"

Использовать контроль версий git в рабочем каталоге только для чтения

Обладая знаниями выше, вы даже можете настроить контроль версий git для рабочего каталога, не имея прав на запись. Если вы используете --git-dir для каждой команды git или для выполнения каждой команды из репозитория (вместо рабочего каталога) вы можете пропустить файл.git и, следовательно, не нужно создавать какие-либо файлы в рабочем каталоге. Смотрите также ответ Леоса

--separate-git-dir вариант для git init (а также git clone) может быть использовано для этого в моей версии git (1.7.11.3). Опция отделяет репозиторий git от рабочего дерева и создает символическую ссылку git, независимую от файловой системы (в форме файла с именем .git) в корне рабочего дерева. Я думаю, что результат идентичен ответу Никса.

git init --separate-git-dir path/to/repo.git path/to/worktree

Я считаю, что проще изменить --work-tree а также --git-dir каталоги, используемые в ответе Никса:

$ cd read_only_repos
$ git --work-tree=/some/readonly/location/foo/ --git-dir=foo init
$ cd foo
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .file_foo
        bar
        ...

Этот подход имеет два преимущества:

  • Это устраняет необходимость иметь какие-либо параметры командной строки или .git файлы. Вы просто работаете в обычном режиме из корня хранилища.
  • Это позволяет вам создавать версии файловой системы, даже если она вам не принадлежит. Git будет писать только в хранилище.

Единственное предостережение, с которым я столкнулся, заключается в том, что вместо .gitignore файл, который вы редактируете info/exclude,

Затем вы можете использовать хранилище read_only_repos/foo в качестве удаленного в ваших собственных репозиториях, даже если исходные файлы не находятся под контролем версий.

Обычно каталог с именем git-репозиторий имеет рабочее дерево в необычном месте с расширением.git, очень похожим на пустой репозиторий.

mkdir ../git_repos/myfiles.git

Если вы предоставили --work-tree вариант во время инициализации, то это автоматически настроило бы core.worktree Переменная config, которая означает, что git будет знать, где найти рабочее дерево, когда вы укажете каталог git.

git --git-dir=../git_repos/myfiles.git --work-tree=. init

Но вы можете установить эту переменную и после факта.

git --git-dir=../git_repos/myfiles.git config core.worktree "$(pwd)"

Как только вы это сделаете, команда add должна работать как положено.

git --git-dir=../git_repos/myfiles.git add foo

Использование git внутри репо:

cd ./backup/git_repos/myfiles
git init --bare
git config core.worktree ../myfiles
git config core.bare false

Отныне вы можете использовать git внутри ./backup/git_repos/myfiles каталог, без установки каких-либо переменных среды или дополнительных параметров.

Вариант 1: core.worktree

Инициализируйте репозиторий без оболочки за пределами пути, который вы хотите отслеживать и установить core.worktreeна путь, который вы хотите отслеживать. Вы можете сделать это с помощью команд терминала, чтобы установить это значение, или напрямую отредактируйте файл конфигурации репозитория, чтобы добавить:

worktree = <path to files to backup>

Не делайте папку репозитория подпапкой этого пути, это будет рекурсивно. Вы могли бы попробовать это и просто проигнорировать папку репозитория, но я думаю, что git не допустит этого сценария.

В вашем случае вы бы пошли в backup/git_repos/ to run the в этом command and could use the--git-dir=. / myfiles`, чтобы переопределить имя папки репозитория по умолчанию. Команды будут выглядеть так:

      cd backup/git_repos 
git init --git-dir=./myfiles
git config core.worktree backup/myfiles

ПРИМЕЧАНИЕ. Недавно я протестировал очень много графических интерфейсов git для Windows, и только Git Extensions поддерживает использование core.worktree для перемещения основного рабочего дерева.

Графические интерфейсы, не поддерживающие core.worktree

SourceTree, Fork, Tower, GitKraken, GitHub Desktop, GitAhead, SmartGit* и Git-Cola. При использовании core.worktree вы захотите придерживаться терминала.

* SmartGit объединяет эту функцию с вариантом 2 и запрашивает файл. Это не требуется для core.worktree.

Вариант 2: --separate-git-dir

Инициализируйте репозиторий по пути, по которому вы хотите сделать резервную копию, используя --separate-git-dir=<path to hold repository data>. This will use the specified path to hold the repository data and create a .git` в месте инициализации, который содержит такую ​​строку:

gitdir: <path to hold repository data>

Для вас команды будут выглядеть так:

      cd backup/myfiles
git init --separate-git-dir=backup/git_repos/myfiles/

И ваш файл в backup/myfiles/ будет содержать gitdir: backup/git_repos/myfiles/

Теперь вы управляете git, обрабатывая местоположение .git файл, поскольку это было расположение репозитория.

Вы можете создать скрипт "nodgit" (No Dot GIT) с чем-то вроде

#!/bin/sh
gits=/usr/local/gits
    x=`pwd`
    testdir() {( cd $1; pwd; )}
    while [ "$x" != "/" ]; do
      y=`echo $x|sed -e "s/\//__/g"`
      if ([ -d "$gits/$y" ]); then
        export GIT_DIR="$gits/$y"
        export GIT_WORK_TREE="$x"
        if ([ "$1" = "nodinit" ]); then
          mkdir -p "$GIT_DIR"
          git init --bare; exit $?
        elif ([ "$1" = "shell" ]); then
          bash; exit $?
        else
          exec git "$@"
        fi
      fi
      x=`testdir "$x/.."`
    done

Вы можете вызвать nodgit вместо git, и он при необходимости установит переменные, ища git-репо. Например, скажем, у вас есть (голое) хранилище в / usr / local / gits / __ home__foo_wibbles и вы находитесь в / home / foo / wibbles / one, тогда он найдет правильный рабочий каталог (/home/foo/wibbles) и репо,

О, вы также можете использовать "nodgit shell", чтобы получить оболочку с правильным набором переменных, чтобы вы могли использовать простые старые команды git.

Предполагая ваш myfiles каталоги уже существуют и имеют некоторый контент, не могли бы вы жить с этим:

cd ~/backup
git init
git add myfiles

.git каталог будет в backup, не в myfiles,

Я создаю сценарии, которые выглядят как

~/ Bin/ ГИТ-слэш:

#!/usr/bin/sh

export GIT_DIR=/home/Version-Control/cygwin-root.git/
export GIT_WORK_TREE=/

git --git-dir=$GIT_DIR --work-tree=$GIT_WORK_TREE "$@"

exit $?

Использование --git_dir=$GIT_DIR излишне, но напоминает мне, что я также могу устанавливать переменные окружения вне скрипта.

Приведенный выше пример предназначен для отслеживания локальных изменений системных файлов cygwin.

Может сделать один такой скрипт для любого крупного проекта, который нуждается в этом - но / без /.git - это мое основное использование.

Вышеуказанное достаточно мало, чтобы создать псевдоним или функцию оболочки, если вы устраняете избыточность.

Если бы я делал это достаточно часто, я бы восстановил рабочее пространство для отображения репозитория

"Boxes, Links, and Parallel Trees: Elements of a Configuration Management System", 
in Workshop Proceedings of the Software Management Conference. 1989.

чей ближайший современный аналог - это выполнение отображений или представлений, поддержка частичных проверок, а также неколокация рабочего пространства и репо.

Другие вопросы по тегам