Чи можу я зберігати папку .git поза файлами, які потрібно відстежувати?


147

У мене незвичайна ідея використовувати git в якості резервної системи. Скажімо, у мене є каталог ./backup/myfiles, і я хочу створити резервну копію, використовуючи git. Щоб зберегти чистоту, я не хочу мати .git-каталог у папці myfiles, тому я подумав, що можу створити ./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

Ви можете побачити повідомлення про помилку, яке я потрапляю туди. Що я роблю неправильно?


9
Як і ваша ідея резервного копіювання, це також можна використовувати для збереження ваших "dotfiles" (.bashrc, .vimrc тощо) у домашньому каталозі, зберігаючи папку .git в іншому місці.
Філіп

6
Найбільш straighforward відповідь: stackoverflow.com/a/19548676/170352 (похований з - за старих upvotes)
Brandon Bertelsen

1
У випадку, якщо у вас немає доступу до запису або ви не хочете вносити жодних змін у робочий каталог (наприклад, додавання .git / і т.д.), ця відповідь Лео (також похований у старих оновленнях) є найкращою.
KobeJohn

1
@Philip, якщо ваш сховище dotfiles також не містить підмодулів Git. Git не підтримує підмодулі в поєднанні із зовнішнім робочим деревом.
maxschlepzig

Відповіді:


101
git --git-dir=../repo --work-tree=. add foo

Це зробить те, що ви хочете, але явно буде смоктати, коли вам доведеться вказувати це з кожною командою git, яку ви коли-небудь використовуєте.

Ви можете експортувати, GIT_WORK_TREE=.і GIT_DIR=../backupGit підбере їх для кожної команди. Це лише комфортно дозволить вам працювати в одному сховищі на оболонці.

Я б краще запропонувати пов'язувати .git-каталог де-небудь ще або створити посилання на .git-каталог із вашого основного каталогу резервного копіювання.


1
Ви можете архівувати те ж саме, не вказуючи git-dir та робоче дерево у кожній команді та без будь-яких символічних посилань. Дивіться мою відповідь.
niks

Мінус символьного посилання полягає в тому, що він існує в межах робочого дерева, і якщо якийсь інший процес видаляє робоче дерево, то ви втратили символьне посилання
Джефф

Крім того, якщо ОП не хотів, щоб у своєму робочому дереві знаходився підкаталог .git, чому б він хотів симпосилання?
Джефф

@Jeff: для компромісу. (У його резервному випадку, витирання його робочого дерева, мабуть, не є для нього більшим занепокоєнням, ніж витирання будь-якого іншого режисера (як, наприклад, саме репо))
Sz.

1
Я використовую це разом з direnv для своїх заміток. Моє робоче дерево знаходиться в папці в Dropbox, а моя папка git десь за межами. Таким чином, я можу легко змінити свої зміни на всіх комп’ютерах, але все-таки зможу перевірити, що змінилося, і виконувати їх лише тоді, коли щось істотне змінилося. Спасибі
Пауло Фагула

170

Вам просто потрібно переконатися, що сховище знає, де знаходиться дерево роботи, і навпаки.

Щоб повідомити сховище, де знаходиться дерево роботи, встановіть значення конфігурації 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 і, отже, не потрібно створювати жодних файлів у робочому каталозі. Дивіться також відповідь Леоса


7
Ви також можете це зробити до наявного репо: перемістіть папку .git туди, куди ви хочете, додайте .git файл, щоб вказати на нього, і тоді ви можете просто продовжувати використовувати репо, як зазвичай
joachim

Зауважте, що ви можете видавати команди git лише з кореня репо. Перехід до папок плутає це! (Це трапляється, чи є задане значення для gitdir відносним чи абсолютним.)
joachim

2
Виправлення цього полягає в тому, щоб вказати 'core.worktree' у фактичному конфігураційному файлі git, тобто в папці, на яку ви вказуєте .git.
Йоахім

2
Так, це я описав у своєму другому реченні своєї відповіді. Звичайно значення конфігурації core.worktreeзберігаються у конфігураційному файлі папки .git, куди вказує файл .git.
niks

1
Я виявляю, що коли я використав ці вказівки, що зроблене репо стало голим сховищем, і це дає помилку fatal: core.worktree and core.bare do not make sense. Схоже, що просто змінити конфігурацію, щоб це не було вирішено.
Стівен Лу

62

--separate-git-dirВаріант git initgit clone) може бути використаний для досягнення цієї мети на мою версію мерзотника ( 1.7.11.3). Параметр відокремлює сховище git від робочого дерева та створює символьну посилання файлової системи agnostic git (у формі файлу з назвою .git) у корені робочого дерева. Я думаю, що результат ідентичний відповіді ніків .

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

2
+1 Використання параметра командного рядка для initсебе виглядає чіткіше і чистіше
goncalopp

у Windows, repo.gitстворюється зі своїм набором прихованих атрибутів. Потім я змінюю її вручну. Чи знаєте ви, чи безпечно це?
ПА.

+1 Так, git спирався на цей варіант командного рядка у версії 1.7.5, який тоді був недоступний (якщо я добре пам'ятаю). Я оновив свою відповідь, щоб запропонувати використовувати цей параметр.
niks

25

Я вважаю простішим перевернути --work-treeта --git-dirкаталоги, які використовуються у відповіді niks:

$ 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як віддалений у власних сховищах, навіть якщо оригінальні файли не знаходяться під контролем версій.


Ну це точно та сама команда. Єдина відмінність, яку я бачу, полягає в тому, що ви поміняли порядок аргументів --work-tree та --git-dir. І, звичайно, ви не створюєте .git файл у робочому каталозі, оскільки у вас немає доступу до нього. Тим не менш, використання версій для управління каталогом без доступу до нього є приємним випадком використання. :-)
niks

3
Ти маєш це. Ключовим моментом є створення репо за межами робочого каталогу.
Лев

4
Мені це подобається - це дозволяє мені використовувати git у каталогах, якими я ділюся з Dropbox, без інших учасників, навіть знаючи, що git використовується.
Квентін Стаффорд-Фрейзер

19

Умовно називати каталог, який представляє собою сховище git, яке має своє робоче дерево у незвичному місці з розширенням '.git', подібно до голого сховища.

mkdir ../git_repos/myfiles.git

Якби ви надали --work-treeопцію під час init, це автоматично встановило б 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_repos/myfiles.git, а не в реальному робочому дереві, "git add foo" буде просто працювати, і вам не потрібно вказувати --git-dir all час.
Стів Фоллі

1
Це правда, але я думаю, що більшість людей прагнуть працювати у своєму робочому дереві, а не у своїх сховищах. Звичайно, якщо ви використовуєте відокремлене робоче дерево, ви, ймовірно, робите щось «особливе», і, можливо, ви можете використовувати макроси, щоб допомогти.
CB Bailey

6

Використовуйте gitвсередині репо:

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

Відтепер ви можете використовувати gitвсередині ./backup/git_repos/myfilesкаталогу, не встановлюючи змінних середовища чи додаткових параметрів.


Це здається найкращою відповіддю, але я розумію, warning: core.bare and core.worktree do not make senseчи означає це, що воно не спрацювало?
hazrpg

1
Я все ще думаю, що це працює, але вона скаржиться на те, що гола під час встановлення робочого дерева. Ось чому я налаштовуюсь core.bareна falseпотім.
To1ne

Ах! Це має більше сенсу зараз. Дякую за це.
hazrpg

1

Ви можете створити сценарій "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 repo. Наприклад, скажіть, що у вас є (голе) репо в / usr / local / gits / __ home__foo_wibbles, і ви перебуваєте в / home / foo / wibbles / one, тоді він знайде правильний робочий каталог (/ home / foo / wibbles) і repo .

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


0

Якщо припустити, що ваші myfilesкаталоги вже є і містять певний вміст, чи можете ви жити з цим:

cd ~/backup
git init
git add myfiles

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


Хоча це дозволило б виправити те, що я хочу, я б краще просто зберігати папку myfiles під git, і більше нічого.
Рорі

Ви можете зберегти вибір файлів, які gitслід відстежувати, використовуючи .gitignoreфайл. Якщо ви додасте *і додасте !myfilesдо нього, відстежуватиметься лише цей каталог. Але якщо ви хочете окремого репо для іншого каталогу, у вас виникнуть проблеми ...
To1ne

0

Я створюю сценарії, схожі на це

~ / bin / git-slash:

#!/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.

Найближчий сучасний аналог - це відображення та перегляди Perforce , що підтримують часткові перевірки, а також нерозбіжність робочого простору та репо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.