git pull, не перебуваючи в каталозі git


308

Скажімо, у мене є каталог /X/Y, який є сховищем git. Чи можна якось викликати команду, як git pullзсередини /X, але орієнтуючись на /X/Yкаталог?

EDIT: Напевно, мені було цікаво конкретно: чи можна це зробити за допомогою команди git, але без зміни каталогів?

ПРИМІТКА. Я прийняв відповідь VonC, оскільки вона набагато елегантніша, ніж попередні варіанти. Люди, які працюють з Git старше 1,8,5, дивіться відповідь bstpierre нижче .


2
Я хотів би додати, що при використанні git-pull всередині гака не вийде, якщо ви не скасуєте GIT_DIR. Відповідні.
zpmorgan

Починаючи з git 1.8.5 (Q4 2013), ви зможете "використовувати команду git, але не змінюючи каталоги". Дивіться мою відповідь нижче
VonC

Відповіді:


453

Починаючи з git 1.8.5 (Q4 2013) , ви зможете "використовувати команду Git, але не змінюючи каталоги".

Так само, як " make -C <directory>", " git -C <directory> ..." каже Git піти туди, перш ніж робити щось інше .

Див здійснювати 44e1e4 по Назрі Ramliy :

Потрібно більше натискань клавіш, щоб викликати команду Git в іншому каталозі, не виходячи з поточного каталогу:

  1. (cd ~/foo && git status)
    git --git-dir=~/foo/.git --work-tree=~/foo status
    GIT_DIR=~/foo/.git GIT_WORK_TREE=~/foo git status
  2. (cd ../..; git grep foo)
  3. for d in d1 d2 d3; do (cd $d && git svn rebase); done

Методи, показані вище, прийнятні для сценаріїв, але занадто громіздкі для швидкого виклику командного рядка.

З цією новою опцією вищезазначене можна зробити за допомогою меншої кількості натискань клавіш:

  1. git -C ~/foo status
  2. git -C ../.. grep foo
  3. for d in d1 d2 d3; do git -C $d svn rebase; done

Оскільки Git 2.3.4 (березень 2015 р.) Та виконувати 6a536e2 Картік Наяк ( KarthikNayak) , gitтрактуватиме " git -C '<path>'" як неоператив , коли <path>він порожній.

" git -C """ ненавмисно гине з помилкою " Cannot change to ''", тоді як оболонка трактує cd "" "як неоперативний.
Приймаючи поведінку оболонки як прецедент, навчіть gitтакож ставитися до -C "" "як до неоперації.


Через 4 роки Git 2.23 (Q3 2019) документи, які git -C """працюють і не змінюють каталог

Так поводиться з 6a536e2 ( git: ставитися до " git -C '<path>'" як неоператор, коли <path>порожній, 2015-03-06, Git v2.3.4).

Це означає, що документація (нарешті) включає:

Якщо " <path>" присутній, але порожній, наприклад -C "", поточний робочий каталог залишається незмінним.


Як git -Cприклад ви можете використовувати Git 2.26 (Q1 2020).

Див. Фіксування b441717 , фіксування 9291e63 , вчинення 5236fce , фіксування 10812c2 , фіксування 62d58cd , фіксування b87b02c , фіксування 9b92070 , фіксування 3595d10 , фіксування f511bc0 , фіксування f6041ab , фіксування f46c243 , вчинення 99c049b , фіксування 3738439 , фіксація 7717242 , фіксація 7717242 , фіксація 7717242 , фіксація 7717242 ( фіг. автор: Дентон Лю ( Denton-L) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті 381e8e9 , 05 лютого 2020 р.)

t1507: в лінію full_name()

Вийшов із реєстрації: Дентон Лю

Раніше ми бігали test_must_fail full_name. Однак test_must_failслід використовувати лише для команд git.
Вбудований full_name()так що ми можемо використовувати test_must_failна gitкоманду безпосередньо.

Коли full_name()було введено в 28fb84382b ("Ввести <branch>@{upstream}нотацію", 2009-09-10, Git v1.7.0-rc0 - злиття ), git -Cпараметр ще не був доступний (оскільки він був введений в 44e1e4d67d (" git: запустити в заданому каталозі) з опцією -C ", 2013-09-09, Git v1.8.5-rc0 - злиття, вказане в партії №5 )).
В результаті функція помічника cdщоразу знімала потребу вручну . Однак, оскільки git -Cце доступно зараз, ми можемо просто використовувати це замість цього та вбудованого full_name().


6
Вау приємно! Це спосіб більш елегантний, тому я відзначу його прийнятим для майбутніх глядачів.
Gavin Anderegg

1
Не працює для мене: # git --version && git -C ~ / .m2 / check master master git версія 1.8.3.4 (Apple Git-47) Невідомий варіант: -C використання: git [--version] [--help ] [-c name = значення] [--exec-path [= <шлях>]] [--html-шлях] [- man-path] [--info-path] [-p | --paginate | --no-пейджер] [--no-change-objects] [--bare] [--git-dir = <path>] [--work-tree = <path>] [- namespace = <name> ] <command> [<args>]
Ян Галинський

7
@JanGalinski Але я згадав "Starting git 1.8.5". Тож git 1.8.3.x ще не знав про цей варіант.
VonC

2
На Ubuntu 12.04 мені довелося встановити новішу версію git. Я зробив це так: apt-get install software-properties-common python-software-propertiesпотім додайте git repo add-apt-repository ppa:git-core/ppa. Останнім кроком є оновлення мерзотника: apt-get update && apt-get upgrade.
ph3nx


54

Редагувати :

Виникла помилка git pull, або ви не можете робити те, що намагаєтесь зробити з цією командою. Однак ви можете зробити це за допомогою вилучення та злиття:

cd /X
git --git-dir=/X/Y/.git fetch
git --git-dir=/X/Y/.git --work-tree=/X/Y merge origin/master

Оригінальна відповідь :

Якщо припустити, що ви керуєте басом або подібним, ви можете це зробити (cd /X/Y; git pull).

Сторінка " git man" вказує деякі змінні (див. "Репозиторій git"), які здаються, що вони повинні допомогти, але я не можу змусити їх працювати правильно (з моїм сховищем в / tmp / ggg2):

GIT_WORK_TREE=/tmp/ggg2 GIT_DIR=/tmp/ggg2/.git git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.

Виконайте команду нижче, поки мій cwd / tmp оновлює це репо, але оновлений файл з'являється у / tmp замість робочого дерева / tmp / ggg2:

GIT_DIR=/tmp/ggg2/.git git pull

Дивіться також цю відповідь на подібне запитання , де демонструються прапорці --git-dirта --work-tree.


Ви спробували використовувати лише GIT_WORK_TREE?
Arrowmaster

@Arrowmaster: так, якщо ви це зробите, git не може знайти .gitкаталог.
bstpierre

Ага, права сторінка повідомляє, що GIT_WORK_TREE не використовується, якщо GIT_DIR не встановлений. Дивно здається, що це не працює тоді, коли обидва використовуються.
Arrowmaster

@Arrowmaster: Мені потрібно задуматися, чи є тут десь помилка. Якщо я це зробити git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pull, я отримую повідомлення про помилку. Але якщо я роблю, git --git-dir=/tmp/ggg2/.git --work-tree=. pullпоки я перебуваю в / tmp, він додає оновлені файли в / tmp як слід.
bstpierre

@bstpierre: У мене немає доступу до системи з мерзотником , встановленим прямо зараз , але якщо б я зробив , я б пробувати інші варіанти з --work-treeпрямо зараз , як --work-tree=/tmp/ggg2/і , --work-tree=/tmp/ggg2/.так як це може бути проблема з тим, як його розбором шляху.
Arrowmaster

32

Ви можете загорнути його у сценарій bash або псевдонім git:

cd /X/Y && git pull && cd -

1
Це, безумовно, робить трюк, але мені цікаво, чи є якийсь спосіб використовувати команду git без зміни каталогів. Я починаю думати, що немає.
Гевін Андерегг

1
і скористайтеся pushd/popdпарою замістьcd/cd-
axd

Або ви можете скористатись (cd xyz && git pull)
допоміжною оболонкою,

30

Ця публікація трохи стара, тому могла бути помилка і вона була виправлена, але я тільки що це зробив:

git --work-tree=/X/Y --git-dir=/X/Y/.git pull origin branch

І це спрацювало. Знадобився у мене хвилину, щоб зрозуміти, що він хотів dotfile та батьківський каталог (у стандартній установці це завжди батько / дочір, але не у ВСІХ налаштуваннях, тому їх потрібно чітко вказати.


Мені подобається це рішення, оскільки воно працює з такими каталогами, як \\ remotemachine \ C $ \ folder \ тощо
twasbrillig

7

Оскільки деякі мої сервери працюють на старих версіях Ubuntu LTS, я не можу легко оновити git до останньої версії (яка підтримує опцію -C, як описано в деяких відповідях).

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

pushd /X/Y
git pull
popd

Або робити це як однолінійний:

pushd /X/Y; git pull; popd

І в Linux, і в Windows є команди pushd і popd.


5

Використовуючи комбінацію pushd, git pullі popdми можемо досягти цієї функції:

pushd <path-to-git-repo> && git pull && popd

Наприклад:

pushd "E:\Fake Directory\gitrepo" && git pull && popd

це дивно. Працює чудово
Stretch0

4

Ви можете написати такий сценарій:

cd /X/Y
git pull

Ви можете назвати це щось на кшталт gitpull.
Якщо ви хочете, щоб він робив довільні каталоги замість /X/Y:

cd $1
git pull

Тоді ви можете зателефонувати за допомогою gitpull /X/Z
останнього, ви можете спробувати знайти сховища. У мене є ~/gitпапка, яка містить сховища, і ви можете використовувати цю функцію, щоб зробити їх усі.

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done

2
Якщо ви хочете зробити це з командного рядка, просто зробити це в субоболочке: (cd /X/Y && git pull).
Каскабель

2

Для тих, хто, як я, що намагався це зробити за допомогою команди drush (Drupal shell) на віддаленому сервері, ви не зможете використовувати рішення, яке вимагає від вас компакт-диск у робочий каталог:

Натомість вам потрібно скористатися рішенням, яке розбиває потяг на збірку та злиття:

drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH fetch origin
drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH merge origin/branch

1

Це може бути схожа проблема, але ви також можете просто ланцюжок команд. напр

По одному рядку

cd ~/Sites/yourdir/web;git pull origin master

Або через SSH.

ssh username@atyourserver.com -t "cd ~/Sites/thedir/web;git pull origin master"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.