GIT: оформление заказа в определенную папку

128

Я хочу использовать что-то похожее на:

git checkout -- <path>/<file>

но я хочу извлечь файл в какую-то папку, которую я выберу, а не перезаписывать локальную <path>/<file>.

Любая идея?

Рафид
источник
2
См .: stackoverflow.com/questions/160608/…
Адам Ванденберг

Ответы:

57

В соответствии с Do a "git export" (например, "svn export")?

Вы можете использовать git checkout-indexдля этого, это команда низкого уровня, если вы хотите экспортировать все, вы можете использовать -a,

git checkout-index -a -f --prefix=/destination/path/

Процитируем страницы руководства:

Последний "/" [в префиксе] важен. Экспортируемое имя буквально начинается с указанной строки.

Если вы хотите экспортировать определенный каталог, есть несколько уловок. Команда принимает только файлы, а не каталоги. Чтобы применить его к каталогам, используйте команду «find» и направьте вывод в git.

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Также на страницах руководства:

Интуитивность здесь не цель. Повторяемость есть.

Hasen
источник
К сожалению, это не будет работать из чистого репозитория git, даже с установленным --prefix :-( (проверено с git 1.9.1)
apeiros
1
если вы хотите проверить ветку / фиксацию GIT_WORK_TREE=../path/to/place git checkout
чистого
4
git worktree(см. ниже) imho - это канонический ответ сегодня, и его можно добавить сюда.
geek-merlin
213

Другое решение, которое немного чище - просто укажите другое дерево работы.

Чтобы проверить все, от HEAD (не индекс) до определенного каталога:

git --work-tree=/path/to/outputdir checkout HEAD -- .

Чтобы извлечь подкаталог или файл из HEAD в конкретный каталог:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname
Адриан Макнейл
источник
4
Незначительное примечание - вам действительно нужен абсолютный путь, поскольку расширение тильды оболочки не происходит, то есть --work-tree=/home/thomasg/okcopyвместо --work-tree=~/okcopy(возможно, использование относительного пути, сидя внутри того же дерева git, тоже работает, но в этом случае заключается безумие и git statusвыходы в R'lyehian)
Том Гудфеллоу
10
Он работает должным образом и со старыми коммитами (например, дает SHA вместо HEAD), однако git statusзатем показывает множество модов (предположительно потому, что индекс теперь соответствует другому каталогу, а не нетронутому нормальному рабочему дереву). git resetвернул его в хорошее состояние.
Том Гудфеллоу
2
Здесь же git statusпоказано много модов, и git resetэто не помогает. Пришлось git checkout -f HEADвосстановить состояние репо.
DUzun
11
К вашему сведению: вам нужно создать каталог самостоятельно, иначе вы получите эту ошибку:fatal: This operation must be run in a work tree
timaschew
13
Это катастрофически изменяет индекс основного рабочего дерева, что обычно плохо. Как предлагает @TomGoodfellow, этого git resetдостаточно, чтобы восстановить работоспособность основного рабочего дерева. Чтобы безопасно экспортировать подкаталоги репозитория в любой SHA1, ветвь или тег без изменения основного рабочего дерева, см . Печально известное git archiveрешение Чарльза Бейли . Точно так же, чтобы безопасно проверять несколько веток одновременно, новая git worktree addподкоманда - ваш друг.
Сесил Карри
25

Для одного файла:

git show HEAD:abspath/to/file > file.copy
Tobu
источник
2
+1 и уточнить «определенную предыдущую фиксацию» (вместо HEAD): это относится к тому, SHA1 IDчто можно легко найти с помощью gitk. Если мне нужно только «извлечь» этот файл во временное место (т.е. не возвращаться), я бы использовал showподкоманду:git show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
ef2011,
19

Вышеупомянутые решения не сработали для меня, потому что мне нужно было проверить конкретную версию дерева с тегами. cvs exportКстати, вот как это предназначено для использования. git checkout-indexне принимает аргумент тега, поскольку извлекает файлы из индекса. git checkout <tag>изменил бы индекс независимо от рабочего дерева, поэтому мне нужно было бы сбросить исходное дерево. Решение, которое сработало для меня, заключалось в клонировании репозитория. Общий клон работает довольно быстро и не занимает много места. При .gitжелании каталог можно удалить.

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

Новые версии git должны поддерживать git clone --branch <tag>автоматическую проверку указанного тега:

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git
proski
источник
3
git --work-tree=/path/to/outputdir checkout <tag> -- .у вас не сработало?
warvariuc 03
1
Нет, это не так. Фактический файл в исходном рабочем каталоге не изменяется, но поэтапная версия теряется и заменяется версией из тега. Особенно плохо, если поэтапная версия содержала тщательно подобранный набор изменений, которые нужно было зафиксировать. Я не хочу, чтобы команда экспорта касалась моего индекса, точка.
proski
19

Если вы работаете со своей функцией и не хотите возвращаться к мастеру, вы можете запустить:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

Он создаст ../myrepo_masterкаталог с masterкоммитами веток, где вы сможете продолжить работу.

itsnikolay
источник
1
Лучший ответ - простой, и, в отличие от git --work-tree=/path/to/outputdir checkout HEAD -- .него, ничего не делает с индексом, просто копирует выбранную ветку в указанное место (с добавлением файла .git).
Роджер Дук
И как мне отменить это изменение?
Скотт П.
@ ScottP. Просто удалите myrepo_masterкаталог
itsnikolay
1
отмена этой подкоманды от worktree:git worktree remove ../myrepo_master
Martijn Dashorst
8

Ответ Адриана был «фатальным: эта операция должна выполняться в дереве работы». У нас сработало следующее.

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

Ноты:

  • --no-checkout Не извлекайте ничего в новое рабочее дерево.
  • --detach Не создавайте новую ветку для нового рабочего дерева.
  • <some-ref> работает с любым рефом, например, работает с HEAD~1 .
  • Очистка с помощью git worktree prune.
Шон Латтин
источник
+1 за комментарии о том, как очистить - все остальные рады испортить текущее репо. только у этого нет побочных эффектов.
Эндрю Хилл
1

Дополнение к ответу @hasen . Чтобы перечислить файлы для оформления заказа , вы можете использовать git ls-filesвместо findlike:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin
snipsnipsnip
источник
Спасибо за правильное использование -z! Приятно, что вы предоставляете сценарий, который не уязвим для определенных видов атак путем инъекций.
Эрике
0

Я определил псевдоним git именно для этого (до того, как нашел этот вопрос).

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

git checkдля разработки ~ / my_project_git

Это, например, приведет к извлечению ветки разработки в каталог "~ / my_project_git".

Это код псевдонима внутри ~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"
CB0
источник
0

Я использую этот псевдоним для проверки ветки во временном каталоге:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

Использование:

git cot mybranch

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

Когда вы закончите, удалите каталог и запустите:

git worktree prune

Это также делается автоматически в псевдониме перед добавлением нового рабочего дерева.

fdietze
источник
0

Используйте, git archive branch-index | tar -x -C your-folder-on-PCчтобы клонировать ветку в другую папку. Думаю, тогда можно скопировать любой нужный вам файл

dqthe
источник