Переключить ветку Git без проверки файлов

100

Можно ли в Git переключиться на другую ветку без проверки всех файлов?

После переключения ветки мне нужно удалить все файлы, восстановить их, зафиксировать и переключиться обратно. Так что извлечение файлов - пустая трата времени (а файлов около 14 000 - это долгая операция).

Чтобы все было понятно:

Все это мне нужно для загрузки документации на GitHub.

У меня есть репозиторий с веткой gh-pages . Когда я перестраиваю документацию локально, я копирую ее в каталог репозитория, фиксирую и отправляю на GitHub. Но я не был счастлив, потому что у меня было две копии документации локально. И я решил создать пустую ветку и после фиксации переключиться на пустую и удалить файлы. Но переключение назад - долгая операция - поэтому я задал этот вопрос.

Я знаю, что могу просто оставить в ветке gh-pages и удалить файлы, но я не люблю грязные рабочие деревья.

тигр
источник
Как долго для вас "длинный"? На какой платформе вы работаете? Вы работаете в сети, например, с NFS или другим совместным доступом к файлам?
Грег Хьюгилл,
Какова цель этого упражнения? Вы хотите иметь две ветки: одна с подробными фиксациями, а вторая - только с крупными изменениями (крупнозернистыми)?
Якуб Наребски
Возможно, дешевле создать временный (или постоянный?) Клон вашей рабочей копии. Мой соответствующий ответ и рецензия показывают, как это работает даже в качестве подкаталога основного репозитория.
krlmlr

Ответы:

106

Да, ты можешь это сделать.

git symbolic-ref HEAD refs/heads/otherbranch

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

git reset
CB Bailey
источник
1
Используйте echo "ebff34ffb665de0694872dceabe0edeaf50ec5a9" > .git/HEADпосле него, git resetчтобы указать ссылку вместо ветки.
cadorn
1
Непосредственная запись в файл HEAD менее надежна. Что делать, если вы находитесь в подкаталоге? Для отделенной головы (голова указывает прямо на SHA1) попробуйте следующее: git update-ref HEAD refs/heads/otherbranch
Александр Берд
2
Если вы хотите перейти в новую ветку из текущей ветки, другой способ сделать это - 1. git stash2. git checkout -b otherBranch3.git stash pop
Винни
@AlexanderBird: git update-refполезно, но также перемещает кончик текущей ветки.
tomekwi
47

Использование только базовых команд git:

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

Отметьте свое текущее местоположение (при необходимости сначала зафиксируйте):

git checkout -b temp

Сбросить (переместить) маркер в другую ветку без изменения рабочего каталога:

git reset <branch where you want to go>

теперь temp и другие ветки указывают на один и тот же коммит, и ваш рабочий каталог не затронут.

git checkout <branch where you want to go>

поскольку ваша ГОЛОВА уже указывает на ту же фиксацию, рабочий каталог не затрагивается

git branch -d temp

Обратите внимание, что эти команды также легко доступны из любого графического клиента.


источник
7
Я бы предпочел git reset --soft <branch where you want to go>не обновлять индекс
JoelFan
7
Я согласен с вашей стратегией избегать команд git сантехники и отдавать предпочтение фарфоровым.
user64141
26

В версии 2.24 git switch есть что-то вроде сейфа git checkout.
Поэтому я переименовал псевдоним ниже git hopдля
«прыжка на ветке , не меняя worktree»

Для удобства читателя:

Пока я думаю что решение Чарльза Бейли является правильным, это решение требует настройки при переключении на что-то, что не является локальной веткой. Также должен быть способ сделать это с помощью обычных команд, которые легко понять. Вот что я придумал:

git checkout --detach
git reset --soft commitish
git checkout commitish

Разъяснил:

  • git checkout --detach такой же как git checkout HEAD^{} что оставляет текущую ветку позади и переходит в «состояние отдельной головы». Так что следующая модификация HEADбольше не затрагивает ни одну ветку. Отсоединение HEADне влияет ни на рабочее дерево, ни на индекс.
  • git reset --soft commitish затем движется HEAD к SHA данного commitish. Если вы хотите обновить и индекс, оставьте это в --softстороне, но я не рекомендую это делать. Это опять же не касается рабочего дерева и (--soft ) не индекса.
  • git checkout commitish затем прикрепляет HEAD к данной commitish(ветке). (Если commitishэто SHA, ничего не происходит.) Это тоже не влияет ни на индекс, ни на рабочее дерево.

Это решение принимает все, что относится к фиксации, поэтому оно идеально подходит для некоторых git псевдонима. Ниже rev-parseприведен всего лишь тест, чтобы убедиться, что ничего не нарушается в цепочке, чтобы опечатки случайно не переключались в состояние отсоединенной головы (восстановление после ошибок было бы намного сложнее).

Это приводит к следующему git hop treeish псевдониму:

git config --global alias.hop '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f'

К вашему сведению, вы можете найти его в моем списке gitпсевдонимов .

Тино
источник
Разве вы не хотите использовать $@вместо $*? Разница в том, что $ @ не раскрывает аргументы в кавычках, внутри которых есть пробелы.
kyb 07
1
@kyb Функциональный трюк украден из другого ответа SO . И $@это здесь окончательно не подразумевается. $*используется вместо $1, такое, что git switch -f bстановится тем же, git switch '-f b'что и должно быть ошибкой. Таким образом, я могу сократить псевдоним, оставив некоторую обработку ошибок, например!f() { [ 1 = $# ] || { echo 'WTF!'; return 1; }; ..
Tino
Очень хорошее решение. Тем более, что его можно использовать для удаленных филиалов!
Nils-o-mat
14

Разве не было бы лучшим решением иметь два рабочих каталога (две рабочие области) с одним репозиторием или даже два репозитория?

В разделе есть инструмент git-new-workdir , contrib/который поможет вам в этом.

Якуб Наребски
источник
Git-new-workdir - это то же самое, что и собственная команда worktree в git? Я использую worktree, когда хочу оформить ветку в другую папку (без клонирования всего репо).
Ryuu
В git-new-worktreeпредшествующей сценарий git worktreeподкоманда; эта команда была недоступна, когда был написан ответ. Например, для сценария требуется поддержка символических ссылок; ИМХО лучше использовать родную поддержку.
Якуб Наребски,
8

Я думаю, вы ищете команду сантехников git read-tree. Это обновит индекс, но не обновит файлы в вашем рабочем каталоге. Например, если предположитьbranch это имя ветки, которую нужно читать:

git ветка дерева чтения

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

git symbolic-ref HEAD refs / главы / ветка
Грег Хьюгилл
источник
нет, мне нужно только переключить ветку, никаких других изменений - так что symbolic-ref достаточно хорош
tig
read-treeгенерирует ошибку: fatal: Not a valid object name branchесли ее еще не git switch branchбыло
Andry
7

Вы можете перезаписать файл HEAD другим именем ветки:

echo "ref: refs / heads / MyOtherBranch"> .git / HEAD

user157005
источник
13
Вероятно, лучше использовать команду symbolic-ref, чтобы сделать это за вас: git symbolic-ref HEAD refs/heads/MyOtherBranch kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html
Грег Хьюгилл,
@GregHewgill, это единственный известный мне способ переместить HEAD в хеш фиксации. Вы можете это сделать git symbolic-ref?
tomekwi
0

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

Норман Рэмси
источник
Вы можете использовать git-new-worktreeдля этого вместо этого (in contrib/)
Якуб Наребски
Я часто делал что-то подобное, то есть копировал мой локальный каталог, прежде чем делать какие-либо «страшные вещи git» как новичок (например, менять ветки и т. Я бы посоветовал людям идти этим путем, пока вы не почувствуете уверенность в своем мерзавце, но по возможности отойдите от него. Сохранение двух разных репозиториев - это нормально, но добавляет уровень сложности и не позволяет вам воспользоваться многими полезными функциями git (слияние, выбор вишни и т. Д.).
Дэвид
0

Если вы просто пытаетесь изменить точку удаленного ветвления, вы можете сделать это с помощью команды «git push», не касаясь локальной копии.

http://kernel.org/pub/software/scm/git/docs/git-push.html

Формат параметра <refspec> - необязательный плюс +, за которым следует исходная ссылка <src>, за которой следует двоеточие:, за которым следует ссылка назначения <dst>. Он используется для указания, с помощью какого объекта <src> обновляется ссылка <dst> в удаленном репозитории.

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

git push origin c5f7eba:foo

Не уверен, что вы хотели этого или нет.

Тим Абелл
источник
На вопрос уже есть ответ: stackoverflow.com/questions/1282639/…
tig
0

вы можете использовать

      1. git checkout -f <new-branch>
      2. git cherry-pick -x <previous-branch-commit-id>

previous-branch-commit-id - это фиксация, из которой вы хотите скопировать старые данные.

Хасина Паркар
источник
0

Или просто используйте патч-файл, чтобы патчить от вашего другого филиала к вашему мастеру

git diff otherbranch master > ~/tmp/otherbranch.diff
git checkout master
git apply ~/tmp/otherbranch.diff
Томер Бен Дэвид
источник
-1

скажем, вы хотите быть в ветке A, но с файлами из ветки B

найти текущую ссылку на фиксацию ветки A с помощью журнала git, например "99ce9a2",

git checkout A
git reset --hard B
git reset 99ce9a2

теперь вы должны быть в ветке A со структурой папок, соответствующей B, которая отображается как неустановленные изменения (история не изменилась).

Дугас
источник