Git: спрятанные головы?
От: Bluebarry  
Дата: 17.12.14 07:38
Оценка:
С Меркуриалом я давно знаком, сейчас разбираюсь с git.

Создаю репозиторий А, делаю в нем пару коммитов, клонирую его в Б (все локально), и делаю еще один коммит в Б. Затем возвращаюсь в А и делаю fetch из Б. По идее, при этом последний коммит должен перетечь в А. Судя по отчету fetch, так оно и есть. Но в истории А этот новый коммит не виден — только два первоначальных. Пробовал всякие опции git log: --all, --branches — не помогает. Пробовал гляделки типа gitk, tortoise — все равно не видно.

Покурил доки. Узнал, что при фетче формируется новая голова FETCH_HEAD, которая и указывает на свежеполученные коммиты. Но git log ее не показывает, ее показывает только git log FETCH_HEAD.

Как-то это странно. В репозитории выросла новая ветка, но увидеть ее не так-то просто. Чтобы увидеть скрытую ветку, я должен знать ее название?!
Может все-таки есть какой-нибудь git log --very_all, который покажет все имеющиеся в репозитории коммиты, ветки, головы? А как увидеть это в GUI-утилитах?
Re: Git: спрятанные головы?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 17.12.14 10:44
Оценка:
Здравствуйте, Bluebarry, Вы писали:

B>С Меркуриалом я давно знаком, сейчас разбираюсь с git.


B>Создаю репозиторий А, делаю в нем пару коммитов, клонирую его в Б (все локально), и делаю еще один коммит в Б. Затем возвращаюсь в А и делаю fetch из Б. По идее, при этом последний коммит должен перетечь в А. Судя по отчету fetch, так оно и есть. Но в истории А этот новый коммит не виден — только два первоначальных. Пробовал всякие опции git log: --all, --branches — не помогает. Пробовал гляделки типа gitk, tortoise — все равно не видно.


B>Покурил доки. Узнал, что при фетче формируется новая голова FETCH_HEAD, которая и указывает на свежеполученные коммиты. Но git log ее не показывает, ее показывает только git log FETCH_HEAD.


B>Как-то это странно. В репозитории выросла новая ветка, но увидеть ее не так-то просто. Чтобы увидеть скрытую ветку, я должен знать ее название?!

B>Может все-таки есть какой-нибудь git log --very_all, который покажет все имеющиеся в репозитории коммиты, ветки, головы? А как увидеть это в GUI-утилитах?

Обычно сценарий использования немного другой. При клонировании автоматически создаётся remote-указатель origin на исходный реп, и вся работа с репом производится через это имя, а не прямым путём к репозиторию:
git fetch origin
В этом случае создаётся ветка origin/master, указывающая на свежеполученную master-ветку исходного репозитория. Её видно в логе, в списке веток (если задать -a или -r), её можно мёрджить с локальными ветками и т. д.

Что касается исходного вопроса, то получить лог с полным списком всех коммитов напрямую нельзя. Есть команда git fsck --unreachable, которая покажет все недостижимые коммиты, а зная хэши коммитов, с ними уже можно работать напрямую, но в этот список попадёт и куча всякого мусора: остатки после объединяющих коммитов (--amend которые), хвосты после сдвига веток "вниз по истории" для отката действий, коммиты из старых веток, на которые был сделан rebase и пр.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[2]: Git: спрятанные головы?
От: Bluebarry  
Дата: 17.12.14 13:22
Оценка:
То есть, как я понял, если не использовать remote refs (типа origin), то при Fetch-е создается безымянная невидимая ветка. Точнее, она не совсем безымянная, на нее указывает FETCH_HEAD.

А вот если сделать fetch несколько раз подряд, то есть получить данные из нескольких репозиториев, то FETCH_HEAD будет указывать на последнюю полученную ветку, а все остальные будут совершенно безымянными, и, практически, невидимыми и недоступными. Разве что, через git fsck..
Печально.

Хорошо, а если я для репозитория RepoA сделаю так:
git remote add rem ../RepoB
git fetch rem

git remote rm rem
git remote add rem ../RepoC
git fetch rem

(RepoB и RepoC - это клоны RepoA, но продвинувшиеся вперед)

Тогда в RepoA появится новая ветка rem/master c двумя головами. Как понять, что у нее две головы? Git log показывает только последнюю голову.
В меркуриале есть hg heads. А если ли аналог в Git?
Кроме того, TortoiseHG показывает всю историю, поэтому таких проблем не возникает.
Re[3]: Git: спрятанные головы?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 17.12.14 14:28
Оценка: 2 (1)
Здравствуйте, Bluebarry, Вы писали:

B>Хорошо, а если я для репозитория RepoA сделаю так:

B>
B>git remote add rem ../RepoB
B>git fetch rem

B>git remote rm rem
B>git remote add rem ../RepoC
B>git fetch rem
B>

B>(RepoB и RepoC - это клоны RepoA, но продвинувшиеся вперед)

B>Тогда в RepoA появится новая ветка rem/master c двумя головами. Как понять, что у нее две головы? Git log показывает только последнюю голову.


Веток с двумя головами не бывает. rem/master станет указывать на master из второго репа, первый при этом затеряется.

B>В меркуриале есть hg heads. А если ли аналог в Git?


К сожалению, с меркуриалом я незнаком, поэтому не знаю, что делает эта команда. Если показывает список всех голов, в том числе "висящих" (на которые нет ни тегов, ни веток), то в гите такого, насколько я знаю, нет. Все висящие коммиты для гита — мусор, который рано или поздно будет удалён garbage collector'ом.

B>Кроме того, TortoiseHG показывает всю историю, поэтому таких проблем не возникает.


Если бы Git и HG были одинаковы во всех мелочах, то не было бы смысла развивать оба. У каждого из них своя концепция, в рамках которой каждый и двигается вперёд. Функционально они практически идентичны (насколько я слышал), т.е. всё, что можно сделать в одном, можно сделать и в другом — пусть порой менее удобно и бо́льшим числом команд. А юзабилити у них, разумеется, нацелено в первую очередь на свой сценарий, и задачи, в него не укладывающиеся, неизбежно пострадают. В гите основной сценарий — не вытягивание веток из рандомных мест, а длительная работа с несколькими постоянными репозиториями. Если у каждого есть своё имя, они нормально сосуществуют и ни малейшим образом друг другу не мешают. На это нацелено и автосоздание origin при клонировании, и автосоздание локальной ветки при чекауте удалённой, и связывание локальных веток с удалёнными при пуше/пулле…
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[3]: Git: спрятанные головы?
От: Jack128  
Дата: 17.12.14 15:14
Оценка:
Здравствуйте, Bluebarry, Вы писали:

B>Кроме того, TortoiseHG показывает всю историю, поэтому таких проблем не возникает.


Ветки в hg и гите — это разные вещи, не нужно их сравнивать.
Re[4]: Git: спрятанные головы?
От: Bluebarry  
Дата: 18.12.14 09:03
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Веток с двумя головами не бывает. rem/master станет указывать на master из второго репа, первый при этом затеряется.

CF> Все висящие коммиты для гита — мусор, который рано или поздно будет удалён garbage collector'ом.

Это плохо вяжется с радостными лозунгами, что в Гите невозможно ничего потерять.
Например, из Pro Git:

As in any VCS, you can lose or mess up changes you haven’t committed yet; but after you commit a snapshot into Git, it is very difficult to lose, especially if you regularly push your database to another repository.


Так все таки, насколько легко или трудно потерять коммиты при работе с гитом?
По моему опыту, в Меркуриале потерять закоммиченные изменения практически невозможно.

Опишу свой workflow для отдельного проекта:

Сначала я создаю репозиторий для проекта.
Я работаю на 3-4 компьютерах, плюс в нескольких виртуалках — для каждого случая создаю клон этого репозитория. Итого 3-10 рабочих клонов (1-2 реально рабочих, остальные — редко используемые). Эти клоны имеют рабочие каталоги, в них я работаю, в них я делаю коммиты.

На каждом компьютере есть директория Myrepos, в которой лежит репозиторий без рабочего каталога.

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

Периодически я делаю hg pull (иногда hg push) между двумя репозиториями на одном компьютере, между компьютером и флешкой. В результате, изменения сделанные в каком-то репозитории, постепенно расползаются по остальным репозиториям. Все репозитории находятся примерно в одном состоянии, и содержат практически все коммиты. И я полностью уверен, что ничего потеряться не может.
Изредка бывает, что я сделаю какое-то незначительное изменение в одном из редко используемых репозиториев, и забуду про него. Но все равно, рано или поздно, я сделаю hg pull из этого репозитория, и забытый коммит разойдется по всем остальным репозиториям — в них появится новая ветка. Рано или поздно, я эту ветку замечу (или глазами, или при эпизодическом hg heads) и закрою ее, возможно, смерджив с текущим коммитом.

В меркуриале, как и в гите, в репозитории можно прописать алиасы — пути к другим репозиториям. При клонировании автоматически создается алиас default. Но я этим практически не пользуюсь, поскольку каждый репозиторий может синхронизироваться с несколькими другими репозиториями, а их пути непостоянны — флешка может быть то диском E, то диском F, флешка может втыкаться в разные компьютеры.

Сейчас вот разбираюсь с гитом, и думаю, не перейти ли мне на него? И удобно ли использовать гит для текущего workflow? Или, может, адаптировать workflow? Пока что, мне кажется, что у меня будут постоянно теряться коммиты.
Re[5]: Git: спрятанные головы?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 18.12.14 11:11
Оценка:
Здравствуйте, Bluebarry, Вы писали:

CF>>Веток с двумя головами не бывает. rem/master станет указывать на master из второго репа, первый при этом затеряется.

CF>> Все висящие коммиты для гита — мусор, который рано или поздно будет удалён garbage collector'ом.

B>Это плохо вяжется с радостными лозунгами, что в Гите невозможно ничего потерять.

B>Например, из Pro Git:
B>

As in any VCS, you can lose or mess up changes you haven’t committed yet; but after you commit a snapshot into Git, it is very difficult to lose, especially if you regularly push your database to another repository.


B>Так все таки, насколько легко или трудно потерять коммиты при работе с гитом?

B>По моему опыту, в Меркуриале потерять закоммиченные изменения практически невозможно.

Боюсь, тут легко начать спорить о том, что такое "легко", а что такое "очень трудно". Просто надо учитывать, в каком контексте это всё рассказывается в Pro Git.
Конечно, если есть желание, то потерять коммит очень легко — как уже говорил, всего лишь сделать commit --amend. Старый коммит потерян, куда уж легче. Но, во-первых, если времени прошло немного, его ещё можно восстановить, глянув хэш через fsck или reflog и навесив ветку/тег. Во-вторых, если проект уже был запушен куда-то, то этот старый коммит сохранится там, пока не перепушишь новую версию (причём так просто ещё и не запушишь, потребуется задать флаг -f для форсированного перезатирания удалённой ветки, что само по себе крайне не рекомендуется). Речь о том, что если не вызывать явно деструктивных команд, данные не потеряешь. Напоролся на жуткое слияние, всё запортил, наворотил нерабочих коммитов — не проблема, всё в репозитории сохранилось, просто откатываешься назад. В процессе ребейза что-то пошло не так — прервал ребейз, всё автоматически вернулось в исходное состояние. В таком вот духе.
Даже в описанном сценарии с вытаскиванием коммитов из репозиториев по прямым путям коммит-то никуда не теряется: в исходном репозитории он остаётся. Это, скорее, не потеря, а "неполучение". Неприятно, согласен, но не критично.

B>Опишу свой workflow для отдельного проекта:

B> <skipped/>
B>Сейчас вот разбираюсь с гитом, и думаю, не перейти ли мне на него? И удобно ли использовать гит для текущего workflow? Или, может, адаптировать workflow? Пока что, мне кажется, что у меня будут постоянно теряться коммиты.

Сходу затруднительно решить, как в таком случае удобнее поступать. Если бы я с такой проблемой столкнулся, я бы для начала зафиксировал букву флэшки — пусть даже они будут разные на разных компах — и провесил remote на флэшку уже по этой букве. Как вариант: сделать в основную файловую систему симлинку на флэшку по её гуиду, тогда не будет зависимости от буквы диска. По возможности, вообще стараюсь унифицировать рабочее окружение на разных компах. Можно subst'ом содать виртуальный диск с одной и той же буквой на всех компах, на котором будет уже одинаковая структура каталогов/репозиториев, а на флэшке, соответственно, один remote на этот виртуальный диск. Можно и без унифицирования обойтись, создав на флэшке десяток удалёнок с уникальными именами для каждого компа, но придётся постоянно вспоминать названия.
Если не хочется создавать remote-имена, можно продолжить работать по путям, сделав алиас, который будет вызывать fetch и автоматически провешивать ветку или тег на FETCH_HEAD (только надо либо гарантированно эту ветку разруливать и удалять перед следующим фетчем либо продумать схему с уникальными именами этих временных веток). Можно попробовать копнуть в направление бандлов, может быть, ими окажется удобнее синхронизировать (тут я, к сожалению, плаваю, сам с ними почти не работал).

Вообще, многое зависит от целей. Чего хочется достичь переходом с hg на git? Если только из-за моды, то смысла нет. Насколько я слышал отзывы меркуриаловцев о гите, всякие подобные мелочи будут постоянно вылезать и раздражать.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re: Git: спрятанные головы?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 18.12.14 19:00
Оценка:
Здравствуйте, Bluebarry, Вы писали:

B>Создаю репозиторий А, делаю в нем пару коммитов, клонирую его в Б (все локально), и делаю еще один коммит в Б. Затем возвращаюсь в А и делаю fetch из Б.


fetch чего? Текущей ветки, другой ветки чем текущая, группы веток, всех веток?
В текущую ветку fetch вообще не должен происходить, для этого пригоден только pull.

Выдала ли эта fetch какую-то явную ошибку?

B> По идее, при этом последний коммит должен перетечь в А. Судя по отчету fetch, так оно и есть. Но в истории А этот новый коммит не виден — только два первоначальных. Пробовал всякие опции git log: --all, --branches — не помогает. Пробовал гляделки типа gitk, tortoise — все равно не видно.


B>Покурил доки. Узнал, что при фетче формируется новая голова FETCH_HEAD, которая и указывает на свежеполученные коммиты. Но git log ее не показывает, ее показывает только git log FETCH_HEAD.


git log без параметров показывает голову текущей ветки. Всё логично.
Re[2]: Git: спрятанные головы?
От: Vuoro  
Дата: 18.12.14 22:53
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Bluebarry, Вы писали:


B>>Создаю репозиторий А, делаю в нем пару коммитов, клонирую его в Б (все локально), и делаю еще один коммит в Б. Затем возвращаюсь в А и делаю fetch из Б.


N>fetch чего? Текущей ветки, другой ветки чем текущая, группы веток, всех веток?

N>В текущую ветку fetch вообще не должен происходить, для этого пригоден только pull.

Наверное, топикстартер хотел получить все коммиты из Б, которых еще нет в А
Re: Git: спрятанные головы?
От: . Великобритания  
Дата: 19.12.14 13:40
Оценка:
Здравствуйте, Bluebarry, Вы писали:

B>С Меркуриалом я давно знаком, сейчас разбираюсь с git.


B>Создаю репозиторий А, делаю в нем пару коммитов, клонирую его в Б (все локально), и делаю еще один коммит в Б. Затем возвращаюсь в А и делаю fetch из Б. По идее, при этом последний коммит должен перетечь в А. Судя по отчету fetch, так оно и есть. Но в истории А этот новый коммит не виден — только два первоначальных. Пробовал всякие опции git log: --all, --branches — не помогает. Пробовал гляделки типа gitk, tortoise — все равно не видно.

Как я понял твой отчёт выглядел так:
kan@snake test]$ git fetch /path/to/repo/b
From /path/to/repo/b
 * branch            HEAD       -> FETCH_HEAD

B>Покурил доки. Узнал, что при фетче формируется новая голова FETCH_HEAD, которая и указывает на свежеполученные коммиты. Но git log ее не показывает, ее показывает только git log FETCH_HEAD.

B>Как-то это странно. В репозитории выросла новая ветка, но увидеть ее не так-то просто. Чтобы увидеть скрытую ветку, я должен знать ее название?!

Ничего скрытого, надо просто было повнимательнее смотреть на то, что тебе git пишет в ответ.

B>Может все-таки есть какой-нибудь git log --very_all, который покажет все имеющиеся в репозитории коммиты, ветки, головы? А как увидеть это в GUI-утилитах?

Когда делаешь fetch, в ответ тебе git пишет всё что скачалось и _куда_. Если делаешь fetch одной ветки (git fetch <url-to-repo-b> <repo's_b_branch_name>), то скачивается в FETCH_HEAD, если "<epo's_b_branch_name>" опустить, команда будет выкачивать текущий бранч (HEAD) удалённого репозитория (это ты и сделал). Если ты добавишь репо как удалённый (git remote add b <url-to-repo-b>), то "git fetch b" скачает все бранчи в отдельное место (refs/remotes/b/*), не пересекающееся с твоими локальными бранчами (refs/heads/*). Что вполне логично — ведь, скажем, твой локальный бранч expermient может не иметь ничего общего с удалённым b/experiment, имя просто случайно совпало.
Т.е. простое скачивание (fetch) данных из удалённого репозитория никогда ничего твоего локального не изменяет.
Ты можешь посмотреть разницу коммитов — что есть там, но нет у тебя (git log HEAD..FETCH_HEAD), либо что есть у тебя, но нет там (git log FETCH_HEAD..HEAD).
Далее. Если ты хочешь удалённое замержить к себе в текущую ветку — делаешь, как ни странно, git merge FETCH_HEAD или git merge refs/remotes/b/master (обычно для юзабельности полное имя "refs/remotes/b/master" можно сократить до "b/master").
В общем-то, если подумать, то в git реализованно управление ветками как это должно быть реализовано в Distributed VCS, а в hg — какая-то хрень непонятная, полу-централизованная.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 19.12.2014 13:55 · . Предыдущая версия .
Re[4]: Git: спрятанные головы?
От: fddima  
Дата: 19.12.14 17:35
Оценка:
Здравствуйте, Jack128, Вы писали:

B>>Кроме того, TortoiseHG показывает всю историю, поэтому таких проблем не возникает.

J>Ветки в hg и гите — это разные вещи, не нужно их сравнивать.
Наверное стоит разобраться в вопросе, а потом уже делать вбросы.
В hg — branches — персистентно именованы (и за это их не все любят).
В git — branches — не именованы, вместо этого это просто указатели на головы веток (и за это их тоже не все любят).
В hg есть bookmarks — которые и являются аналогом git branches (которые тоже имеют свои тараканы).
При этом всём — ветки в обоих SCM абсолютно одинаковы, — "ветка" есть цепочка коммитов, обычно с как-то идентифицируемой головой.
Собственно говоря тэги в обоих системах — ещё один альтернативный способ указать голову, но они, в отличии от тех же bookmarks — не двигаются автоматически.
Re[5]: Git: спрятанные головы?
От: Jack128  
Дата: 19.12.14 18:34
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, Jack128, Вы писали:


B>>>Кроме того, TortoiseHG показывает всю историю, поэтому таких проблем не возникает.

J>>Ветки в hg и гите — это разные вещи, не нужно их сравнивать.
F>Наверное стоит разобраться в вопросе, а потом уже делать вбросы.
F>В hg — branches — персистентно именованы (и за это их не все любят).
F>В git — branches — не именованы, вместо этого это просто указатели на головы веток (и за это их тоже не все любят).
F>В hg есть bookmarks — которые и являются аналогом git branches (которые тоже имеют свои тараканы).
F>При этом всём — ветки в обоих SCM абсолютно одинаковы, — "ветка" есть цепочка коммитов, обычно с как-то идентифицируемой головой.
F>Собственно говоря тэги в обоих системах — ещё один альтернативный способ указать голову, но они, в отличии от тех же bookmarks — не двигаются автоматически.

ты так говоришь, как будто branches и ветки — это разные вещи. можно англоязычный аналог слова "ветки"?
Re[6]: Git: спрятанные головы?
От: fddima  
Дата: 21.12.14 15:53
Оценка:
Здравствуйте, Jack128, Вы писали:

J>ты так говоришь, как будто branches и ветки — это разные вещи. можно англоязычный аналог слова "ветки"?

Нет, я лишь говорю о том, что branches в hg и git одинаковые. Непосредственное поведение одноименных команд — да, действительно различно. Вместе с тем общий аналогичный базис в этих двух scm — есть, поэтому их сравнивать вполне корректно.
Re: Git: спрятанные головы?
От: Bluebarry  
Дата: 21.01.15 16:50
Оценка:
CF>Вообще, многое зависит от целей. Чего хочется достичь переходом с hg на git?
Например, использовать GitHub. Волей-неволей, придется освоить Гит..

Я существенно продвинулся в изучении гита. Прочитал "Про Гит 2", и еще кучу статей.
Большое спасибо всем за ответы. Они мне реально помогли.

Я все-таки, прихожу к выводу, что Меркуриал мне для работы удобнее. Так что, Гитом я буду пользоваться только обмена с ГитХабом (или с другими гит-хостингами).

Но, вернусь, все-таки, к исходному вопросу.
Есть проект, над которым я работаю. У меня два компа — десктоп и лаптоп, на обоих есть клоны этого проекта. Еще один клон проекта находится на флешке.
Вот поработал я на десктопе, сделал несколько коммитов. А в поездку взял с собой лаптоп, и тоже сделал несколько коммитов. Все, история разветвилась, но я, возможно, об этом пока не подозреваю.
Теперь я хочу перенести все новые коммиты с лаптопа на флешку, причем, на на флешке, возможно уже есть коммиты, сделанные на десктопе. Какой командой это лучше всего сделать?
Какой командой затем перенести все новые коммиты с флешки на десктоп (на флешке, возможно, раздвоившаяся история)?
И как обнаружить это раздвоение истории на десктопе и гарантированно не потерять лаптопные коммиты?

Другими словами. Я хочу обнаруживать и разруливать конфликты и выполнять мерджи на десктопе в спокойной обстановке. Я не хочу заниматься этим на лаптопе, а также во время переноса данных с компа на флешку и с флешки на комп. И при этом я не хочу свои коммиты.
С Меркуриалом все это делается просто.
А возможно ли это с Гитом? У меня как-то не получается...
Re[2]: Git: спрятанные головы?
От: . Великобритания  
Дата: 21.01.15 18:22
Оценка: 1 (1)
Здравствуйте, Bluebarry, Вы писали:

B>Я существенно продвинулся в изучении гита. Прочитал "Про Гит 2", и еще кучу статей.

B>Большое спасибо всем за ответы. Они мне реально помогли.

B>Я все-таки, прихожу к выводу, что Меркуриал мне для работы удобнее. Так что, Гитом я буду пользоваться только обмена с ГитХабом (или с другими гит-хостингами).


B>Но, вернусь, все-таки, к исходному вопросу.

B>Есть проект, над которым я работаю. У меня два компа — десктоп и лаптоп, на обоих есть клоны этого проекта. Еще один клон проекта находится на флешке.
B>Вот поработал я на десктопе, сделал несколько коммитов. А в поездку взял с собой лаптоп, и тоже сделал несколько коммитов. Все, история разветвилась, но я, возможно, об этом пока не подозреваю.
B>Теперь я хочу перенести все новые коммиты с лаптопа на флешку, причем, на на флешке, возможно уже есть коммиты, сделанные на десктопе. Какой командой это лучше всего сделать?
делаешь "git push". Оно пытается послать новые коммиты лаптопа в "центральный" флешковый репозиторий.

B>Какой командой затем перенести все новые коммиты с флешки на десктоп (на флешке, возможно, раздвоившаяся история)?

"git pull"

B>И как обнаружить это раздвоение истории на десктопе

Просто смотришь разницу истории, например "git log branchX..branchY" — показывает список коммитов, которые есть в Y, но ещё нет в X. И тут четыре комбинации:
  1. branchA..branchB — пусто, branchB..branchA — пусто => оба брача синхронизированы.
  2. branchA..branchB — не пусто, branchB..branchA — пусто => branchB новее.
  3. branchA..branchB — пусто, branchB..branchA — не пусто => branchA новее.
  4. branchA..branchB — не пусто, branchB..branchA — не пусто => diverged history, нужно явно мержить.

B> и гарантированно не потерять лаптопные коммиты?

Потерять коммиты можно только если ты специально их решишь удалить. Для этого нужно выполнить две-три хитрые команды, с хитрыми ключами. Проще сделать "rm -rf /".

B>Другими словами. Я хочу обнаруживать и разруливать конфликты и выполнять мерджи на десктопе в спокойной обстановке. Я не хочу заниматься этим на лаптопе, а также во время переноса данных с компа на флешку и с флешки на комп. И при этом я не хочу свои коммиты.

B>С Меркуриалом все это делается просто.
B>А возможно ли это с Гитом? У меня как-то не получается...
Так, это немножко другой сценарий. Если ты не хочешь делать мержи на лаптопе, то на флешке можно завести специальный лаптопный бранч, в который ты будешь пушить только с лаптопа, поэтому конфликты возникать не должны. Т.е. на лаптопе делаешь "git push <flash_drive_repo> HEAD:laptop_branch". Потом на десктопе делаешь "git fetch <flash_drive_repo> laptop_branch && git merge FETCH_HEAD" — ну и резолвишь конфликты|етс. Между fetch и merge можешь сделать "git log HEAD..FETCH_HEAD" и "git log FETCH_HEAD..HEAD", чтобы изучить разницу истории, как я описал выше.

Интересно, как этот сценарий ты делаешь в hg?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 21.01.2015 18:27 · . Предыдущая версия . Еще …
Отредактировано 21.01.2015 18:25 · . Предыдущая версия .
Re[3]: Git: спрятанные головы?
От: Bluebarry  
Дата: 22.01.15 10:45
Оценка:
Здравствуйте, ., Вы писали:

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

Но если понадобится сделать новую ветку feachure_branch, то делать ее придется на обоих компьютерах: laptop_feachure_branch, desctop_feachure_branch. К тому же, у меня есть еще один лаптоп...
То есть, придется иметь дело с декартовым произведением веток и компьютеров.

.> Т.е. на лаптопе делаешь "git push <flash_drive_repo> HEAD:laptop_branch".

То есть, при переносе данных с компа на флешку, мне нужно помнить, какие ветки есть на данном компе, и указать их в параметрах к "git push"

.> Потом на десктопе делаешь "git fetch <flash_drive_repo> laptop_branch && git merge FETCH_HEAD" — ну и резолвишь конфликты|етс. Между fetch и merge можешь сделать "git log HEAD..FETCH_HEAD" и "git log FETCH_HEAD..HEAD", чтобы изучить разницу истории, как я описал выше.

При следующем fetch-е FETCH_HEAD перейдет на новое место, и старый FETCH_HEAD может стать труднодоступным и потеряться.
Поэтому изучать разницу историй и мержить нужно здесь и сейчас, до следующего fetch-а.

.>Интересно, как этот сценарий ты делаешь в hg?

Команда "hg pull" без дополнительных параметров вытягивает из удаленного репозитория все новые коммиты из всех веток. Этой командой я переношу данные с флешки на комп и обратно. Никаких вопросов при этом у Меркуриала не возникает, он просто перетягивает все новое. Если в репе появились новые ветки (именованные, или неименованные), они тоже перетянутся, никаких дополнительных параметров к "hg pull" указывать не нужно.

Историю я изучаю с помощью TortoiseHG Workbench. Там по умолчанию видны все ветки и головы.
Есть команда "hg heads". которая показывает все незакрытые головы. Если какая-то именованная ветка имеет более одной головы, это повод разобраться. Но это не обязательно делать сразу после pull-а. Можно и потом, после следующего pull-а. Можно и на другом компьютере (на десктопе с большим экраном разбирать конфликты гораздо приятнее, чем в поезде на маленьком лаптопе).
Конечно, резолвинг лучше не затягивать. Чем позже, тем сложнее его будет делать. Но, в любом случае, висящие головы никуда не пропадут, и будут все это время мозолить глаза.
Re[4]: Git: спрятанные головы?
От: . Великобритания  
Дата: 22.01.15 16:12
Оценка:
Здравствуйте, Bluebarry, Вы писали:

B>Здравствуйте, ., Вы писали:


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

B>Но если понадобится сделать новую ветку feachure_branch, то делать ее придется на обоих компьютерах: laptop_feachure_branch, desctop_feachure_branch. К тому же, у меня есть еще один лаптоп...
B>То есть, придется иметь дело с декартовым произведением веток и компьютеров.
Что в общем-то в точности соответствует тому, что происходит в реальности.

.>> Т.е. на лаптопе делаешь "git push <flash_drive_repo> HEAD:laptop_branch".

B>То есть, при переносе данных с компа на флешку, мне нужно помнить, какие ветки есть на данном компе, и указать их в параметрах к "git push"
Если это частая операция, то можно настроить fetch/push правила. Скажем указать git config remote.origin.push refs/heads/*:refs/remotes/origin/LAPTOP/*". Т.е. все локальные ветки будут пушиться в удалённый репозиторий с префиксом LAPTOP.
Найти все ещё не замерженные ветки "git branch --no-merged".

.>> Потом на десктопе делаешь "git fetch <flash_drive_repo> laptop_branch && git merge FETCH_HEAD" — ну и резолвишь конфликты|етс. Между fetch и merge можешь сделать "git log HEAD..FETCH_HEAD" и "git log FETCH_HEAD..HEAD", чтобы изучить разницу истории, как я описал выше.

B>При следующем fetch-е FETCH_HEAD перейдет на новое место, и старый FETCH_HEAD может стать труднодоступным и потеряться.
FETCH_HEAD это просто для краткости. Можешь задать имя явно. Сделай "git fetch <flash_drive_repo> laptop_branch:something_to_merge", коммиты заберутся в новую локальную ветку something_to_merge. Или настрой fetch-правила, если делаешь подобное часто.

B>Поэтому изучать разницу историй и мержить нужно здесь и сейчас, до следующего fetch-а.

Если выразиться точнее: перед изучением истории и мержем просто делаешь fetch того, что ты собираешься изучать и мержить здесь и сейчас. Если ты передумал мержить и решил взяться за что-то другое, просто создай ветку на потом "git branch i_do_it_later FETCH_HEAD" и вернись к ней позже.

.>>Интересно, как этот сценарий ты делаешь в hg?

B>Команда "hg pull" без дополнительных параметров вытягивает из удаленного репозитория все новые коммиты из всех веток. Этой командой я переношу данные с флешки на комп и обратно. Никаких вопросов при этом у Меркуриала не возникает, он просто перетягивает все новое. Если в репе появились новые ветки (именованные, или неименованные), они тоже перетянутся, никаких дополнительных параметров к "hg pull" указывать не нужно.
Да, для такого юскейс в git надо настроить fetch/push refspec правила. А в hg этот юскейс вшит в саму систему.

B>Историю я изучаю с помощью TortoiseHG Workbench. Там по умолчанию видны все ветки и головы.

B>Есть команда "hg heads". которая показывает все незакрытые головы. Если какая-то именованная ветка имеет более одной головы, это повод разобраться. Но это не обязательно делать сразу после pull-а. Можно и потом, после следующего pull-а. Можно и на другом компьютере (на десктопе с большим экраном разбирать конфликты гораздо приятнее, чем в поезде на маленьком лаптопе).
B>Конечно, резолвинг лучше не затягивать. Чем позже, тем сложнее его будет делать. Но, в любом случае, висящие головы никуда не пропадут, и будут все это время мозолить глаза.
Понятно. В hg под веткой называется именованное множество безымянных(?) голов (указателей на коммит). В гит ветка это просто именованный указатель на коммит. Множеств веток нет, но можно соорудить с помощью правил.
А что произойдёт, если ты на двух лаптопах создашь две ветки, со случайно совпавшим именем, например experiment? Как это запушится на флешку?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Git: спрятанные головы?
От: Bluebarry  
Дата: 23.01.15 11:49
Оценка:
.>Понятно. В hg под веткой называется именованное множество безымянных(?) голов (указателей на коммит).
Не совсем там. Ветка (brunch) в Меркуриале — это множество коммитов. Все ветки имеют имена. По-умолчанию, в новом репозитории создается ветка "default".
Добавление каждого коммита происходит в контексте какой-то ветки, и данный коммит навечно принадлежит этой ветке.
У коммита могут быть потомки. По-умолчанию, коммит-потомок принадлежит той же ветке, что и родительский коммит. Но можно указать другое имя ветки, например, "experiment". И тогда, с этого нового коммита начнется новая ветка "experiment".
У коммита может быть несколько потомков. Причем эти потомки могут принадлежать и к разным веткам, и к одинаковым. Ограничений нет. Например, коммит из ветки "default" может иметь 5 потомков: два в ветке "default", два в ветке "experiment" и один в ветке "test".
Получить несколько потомков можно разными способами:
1) Сделали коммит, — не понравилось. Откатились назад, пошли другим путем. Сделали коммит — вот оно, появилось разветвление.
2) В разных репозиториях (возможно, на разных компах, разные разработчики) добавили несколько коммитов. Сделали pull/push — вот оно, разветвление.
Таким образом, каждая ветка в Меркуриале сама может ветвиться — распадаться на "веточки". Вот эти "веточки" обычно и называют "неименованные ветки", хотя это, наверное, не совсем правильно.
Голова (head) в Меркуриале — это коммит, не имеющий потомков в своей ветке. То есть, ветка на нем заканчивается. Каждая голова (так как это коммит), принадлежит какой-то ветке. Каждая ветка имеет, по крайней мере, одну голову. Но может иметь и несколько голов. В Меркуриале это совершенно нормально.

.>А что произойдёт, если ты на двух лаптопах создашь две ветки, со случайно совпавшим именем, например experiment? Как это запушится на флешку?

Команда "hg push" имеет ряд ограничений, и по-умолчанию, не позволяет создавать новые ветки. Опция --new_branch разрешает пушить новую именованную ветку, а опция --force пушит вообще все.
Я обычно пользуюсь командой "hg pull". Она таких ограничений не имеет, и затягивает все новые коммиты со всеми ветвлениями.
Так что, все запулится без проблем. И запушится без проблем, если добавить "--force"
В результате, на флешке будет новая ветка "experiment". Одна ветка "experiment", а не две! Команда "hg branches" показывает все ветки — ветка "experiment" действительно одна. Она будет состоять из двух "веточек", причем эти веточки, возможно, даже не будут связаны друг с другом. Ничего страшного. В Меркуриале ветки могут быть неодносвязными.
Конечно, неодносвязная ветка несет в себе некоторые неудобства. И Меркуриал, в разумной мере, сопротивляется этому. По крайней мере, напрямую создать неодносвязную ветку не получится — придется указывать дополнительные опции, типа "--force". Но, в рассматриваемом случае, Меркуриал ничего сделать не может: неодносвязные "веточки" созданы на разных компах, и ему приходится с этим смириться.


B>>То есть, придется иметь дело с декартовым произведением веток и компьютеров.

.>Что в общем-то в точности соответствует тому, что происходит в реальности.
Ну почему? Есть, скажем ветка "Stable" для стабильных релизов. Она одна. И если какой-то Вася сделает два клона репозитория, то что же, у всех должны появиться ветки "Vasya1_Stable", и "Vasya2_Stable"?
Нет, просто у Васи будет та же самая ветка "Stable", как и во всех остальных репах.

B>>Поэтому изучать разницу историй и мержить нужно здесь и сейчас, до следующего fetch-а.

.>Если выразиться точнее: перед изучением истории и мержем просто делаешь fetch того, что ты собираешься изучать и мержить здесь и сейчас. Если ты передумал мержить и решил взяться за что-то другое, просто создай ветку на потом "git branch i_do_it_later FETCH_HEAD" и вернись к ней позже.
Суть остается прежней: между fetch-ем и merge-ем желательно ничего не делать: никаких commit-ов, fetch-ей, pull-ов.
И при переносе данных из одного репозитория в другой (push, pull, fetch) необходимо знать обстановку в обоих репах. И, возможно, нужно будет сделать дополнительные действия.

.>Да, для такого юскейс в git надо настроить fetch/push refspec правила. А в hg этот юскейс вшит в саму систему.

Надо будет мне поизучать эти правила.
Re[6]: Git: спрятанные головы?
От: . Великобритания  
Дата: 23.01.15 15:04
Оценка:
Здравствуйте, Bluebarry, Вы писали:

.>>Понятно. В hg под веткой называется именованное множество безымянных(?) голов (указателей на коммит).

B>Не совсем там. Ветка (brunch) в Меркуриале — это множество коммитов. Все ветки имеют имена. По-умолчанию, в новом репозитории создается ветка "default".
Эээ. Ровно так как я написал. Имя ветки == имя множества голов. Голова — указатель на коммит "без потомков", branch tip.

B>Добавление каждого коммита происходит в контексте какой-то ветки, и данный коммит навечно принадлежит этой ветке.

B>У коммита могут быть потомки. По-умолчанию, коммит-потомок принадлежит той же ветке, что и родительский коммит. Но можно указать другое имя ветки, например, "experiment". И тогда, с этого нового коммита начнется новая ветка "experiment".
B>У коммита может быть несколько потомков. Причем эти потомки могут принадлежать и к разным веткам, и к одинаковым. Ограничений нет. Например, коммит из ветки "default" может иметь 5 потомков: два в ветке "default", два в ветке "experiment" и один в ветке "test".
B>Получить несколько потомков можно разными способами:
B>1) Сделали коммит, — не понравилось. Откатились назад, пошли другим путем. Сделали коммит — вот оно, появилось разветвление.
Разветвление это только если есть два коммита с одинаковым родителем. Смотри DAG. Узлы DAG — коммиты, рёбра — отношение родитель-ребёнок. Собственно почему мерж называется мержем — это когда два разветвления сливаются.

                 A---B---C topic
                /         \
           D---E---F---G---H master

E — это коммит с двумя разными ребёнками A и F, точка начала ветвления.
H — это merge commit, коммит с двумя (или более, для git) родителями.

А вот в меркуриал всё переусложнено. Есть слияние голов ветки и есть слияние веток. Очень запутывает. Плюс бесмыссленное ограничение, что мержить можно только две ветки.

B>2) В разных репозиториях (возможно, на разных компах, разные разработчики) добавили несколько коммитов. Сделали pull/push — вот оно, разветвление.

B>Таким образом, каждая ветка в Меркуриале сама может ветвиться — распадаться на "веточки". Вот эти "веточки" обычно и называют "неименованные ветки", хотя это, наверное, не совсем правильно.
B>Голова (head) в Меркуриале — это коммит, не имеющий потомков в своей ветке. То есть, ветка на нем заканчивается. Каждая голова (так как это коммит), принадлежит какой-то ветке. Каждая ветка имеет, по крайней мере, одну голову. Но может иметь и несколько голов. В Меркуриале это совершенно нормально.
Как я понял, в гите "ветка" это просто ветка, с одним концом, ссылка (ref) на некоторый коммит. А в меркуриал это толстая ветка с пачкой веточек-концов (которые называются heads). Плюс имя "толстой ветки" зашивается в самом коммите, иначе говоря, коммиты имеют метку "имя ветки". В гите ветки на коммиты никак не влияют.

.>>А что произойдёт, если ты на двух лаптопах создашь две ветки, со случайно совпавшим именем, например experiment? Как это запушится на флешку?

B>Команда "hg push" имеет ряд ограничений, и по-умолчанию, не позволяет создавать новые ветки. Опция --new_branch разрешает пушить новую именованную ветку, а опция --force пушит вообще все.
B>Я обычно пользуюсь командой "hg pull". Она таких ограничений не имеет, и затягивает все новые коммиты со всеми ветвлениями.
B>Так что, все запулится без проблем. И запушится без проблем, если добавить "--force"
B>В результате, на флешке будет новая ветка "experiment". Одна ветка "experiment", а не две! Команда "hg branches" показывает все ветки — ветка "experiment" действительно одна. Она будет состоять из двух "веточек", причем эти веточки, возможно, даже не будут связаны друг с другом. Ничего страшного. В Меркуриале ветки могут быть неодносвязными.
B>Конечно, неодносвязная ветка несет в себе некоторые неудобства. И Меркуриал, в разумной мере, сопротивляется этому. По крайней мере, напрямую создать неодносвязную ветку не получится — придется указывать дополнительные опции, типа "--force". Но, в рассматриваемом случае, Меркуриал ничего сделать не может: неодносвязные "веточки" созданы на разных компах, и ему приходится с этим смириться.
Проблема в том, что в меркуриал чужой репозиторий диктует имена веток тебе, имена веток глобальны (это же жуть для распределённой системы, имхо). В гите сам выбираешь как локальные ветки соотносятся с удалёнными. Т.е. случайное совпадение имён это локальная проблема обмена между двумя репозиториями, можно локальную ветку "a" замапить на удалённую ветку "b".

B>>>То есть, придется иметь дело с декартовым произведением веток и компьютеров.

.>>Что в общем-то в точности соответствует тому, что происходит в реальности.
B>Ну почему? Есть, скажем ветка "Stable" для стабильных релизов. Она одна. И если какой-то Вася сделает два клона репозитория, то что же, у всех должны появиться ветки "Vasya1_Stable", и "Vasya2_Stable"?
B>Нет, просто у Васи будет та же самая ветка "Stable", как и во всех остальных репах.
Как это "у всех"? Это же распределённая система. Только у тех, кто фетчит (или кому пушат) из этих двух клонов.

B>>>Поэтому изучать разницу историй и мержить нужно здесь и сейчас, до следующего fetch-а.

.>>Если выразиться точнее: перед изучением истории и мержем просто делаешь fetch того, что ты собираешься изучать и мержить здесь и сейчас. Если ты передумал мержить и решил взяться за что-то другое, просто создай ветку на потом "git branch i_do_it_later FETCH_HEAD" и вернись к ней позже.
B>Суть остается прежней: между fetch-ем и merge-ем желательно ничего не делать: никаких commit-ов, fetch-ей, pull-ов.
Не понял. Когда ты сделал fetch в свою локальную ветку i_do_it_later — оно у тебя будет локально, до тех пор пока ты эту ветку не грохнешь.

B>И при переносе данных из одного репозитория в другой (push, pull, fetch) необходимо знать обстановку в обоих репах. И, возможно, нужно будет сделать дополнительные действия.

Не понял. Какую обстановку? fetch вообще ничего не меняет, просто скачивает отсутствующие коммиты в локальный репо. push сработает, если история не разветвилась. Если разветвилась и мержить некогда или не хочется локально, можешь сделать push в новую удалённую ветку, и замержить уже в удалённом репозитории потом.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.