Могу ли я хранить папку.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.worktreeSourceTree, 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.
чей ближайший современный аналог - это выполнение отображений или представлений, поддержка частичных проверок, а также неколокация рабочего пространства и репо.