LINUX.ORG.RU

Вопрос про Git. Он, правда, позволяет так легко потерять данные?

 , ,


9

7

Я тут на пробу пытаюсь парочку репозиториев перевести с привычного Mercurial на инопланетной логики Git в надежде разобраться с последним. И, ладно бы только логика работы, к ней можно привыкнуть. Но я уже несколько раз терял свои наработки с Git, чего с Mercurial не было никогда за всю историю. Пару раз терял так, что концов не найти, но вот сейчас всю цепочку отследить попробовать можно. Посему и прошу комментариев народа опытного.

Суть такая. Есть поднятый весной и так и не развитый репозиторий https://github.com/Balancer/bors-3rd-bootstrap3

Сейчас решил перекинуть туда код (со всей историей) по работе с bootstrap из ядра фреймворка, которое лежит в Mercurial на Bitbucket. Благо, есть такая прекрасная штука, как hg-git. Перенос файлов со всеми изменениями из репы в репу под Git возможен, но выглядит это чудовищно. Посему, решил вынести сперва отдельный маленький локальный репозиторий Mercurial с этими файлами, к нему подтянуть дерево Git, смержить средствами Mercurial и запушить в репу Git.

Сделать это было чуть дольше, чем написать предыдущий абзац, но работа небольшая, всё было проведено легко и непринуждённо. На GitHub'е появился объединённый модифицированный код. Всё прекрасно.

Дальше начинаются вещи непонятные. Я работал также с другой машины, там были мелкие правки (типа composer.json в корне). Решил всё объединить. Точную последовательность не помню, но, скорее всего обычные git pull && git push на другой машине.

После этого, чтобы точно убедиться, что изменения синхронизированы, провёл после git fetch (там --bare) на первой машине git push... И увидел странное:

To git@github.com:Balancer/bors-3rd-bootstrap3.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:Balancer/bors-3rd-bootstrap3.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Ну, что, Google в помощь, и первый же совет, который нахожу — воспользоваться ключиком «-f». Не вопрос. У нас же DVCS, даже если что-то не так, всегда можно откатить и т.п. Логика, привитая Mercurial'ом, ага...

Ничтоже сумняшеся, обновляю composer на другой машине и... вижу, что всех изменений, которые я переносил в эту репу нет. Удивляюсь. Вызываю git log --graph (вот почему в git по дефолту все команды такие длинные и несуразные?) — чистота. Всё в превозданном виде семимесячной давности, без переноса нового кода с основного репо.

Лезу на GitHub — и вот тут становится совсем интересно. Те изменения, что я накатывал и которые там были, теперь там отсутствуют o_O

Так вот, вопрос. Это я их не вижу, или это в Git так легко, одним движением руки можно убить безвозвратно серию коммитов с историей? o_O Если первое — то вопрос, как вернуть эти изменения. В основной репе я их уже успел прибить, но всегда можно откатить и повторить перенос. Придётся повозиться, но задача не столь сложная. Но хочется разобраться. Ибо если в Git так легко потерять изменения, то как с ним вообще люди живут?

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)
Ответ на: комментарий от waker

Можешь воспроизвести?

могу

Ок, математик из анекдота detected. Проехали.

KRoN73 ★★★★★
() автор топика

Это я их не вижу, или это в Git так легко, одним движением руки можно убить безвозвратно серию коммитов с историей?

Если взял в руки топор, прицелился в ногу и на вопрос: «А ты точно сюда бить хочешь?» ответил да и ударил - то пришить обратно ногу можно конечно(если знать как). Но лучше по ноге не бить, а рубить деревья, например.

То же и с git, при использовании --force. И с fsck на примонтированном на запись разделе.

Рекомендую ТСу живительного чтения ProGit, после этой книги 90% вопросов о том как работать с git отпадут сами.

А так - man git reset, man git rebase, ну и про reflog уже говорили вроде

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 1)

вот почему в git по дефолту все команды такие длинные и несуразные?

Потому что есть гибкая система алиасов(я не про алиасы шелла, у git-а есть свои), позволяющая настроить какие тебе угодно сокращения.

Пользоваться дефолтом - дело привычки. Не хочешь - алиасы в помощь.

Pinkbyte ★★★★★
()
Ответ на: комментарий от KRoN73

Машина должна работать, человек — думать

Не знал, что мы научили машины думать...

такой рутиной должна заниматься именно система

Конечно могу ошибаться, но такую штуку поддерживает любая система для ревью, поскольку другого способа криптографического подтверждения «я смотрел здесь» нету.

Её неприкосновенность

История гита неприкосновенна, как история меркуриала. Или я что-то пропустил и меркуриал запрещает удалять бранчи?

Macil ★★★★★
()
Ответ на: комментарий от Pinkbyte

Если взял в руки топор, прицелился в ногу и на вопрос: «А ты точно сюда бить хочешь?» ответил да

Некорректная аналогия. Для топора не ставится целью задача удобной работы по сохранению и резервированию ног. Зато от DVCS ожидается надёжное сохранение информации. При чём в XXI веке считается хорошим тоном иметь защиту от некорректных действий пользователя, что в применении к DVCS формируется в ожидание надёжного хранения всех действий с лёгкой возможностью возвращения старых данных.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Pinkbyte

«После сборки доработать напильником»... Мне это стало надоедать ещё лет 15 назад. Компьютер для разработчика, а не разработчик для компьютера.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Зато от DVCS ожидается надёжное сохранение информации. При чём в XXI веке считается хорошим тоном иметь защиту от некорректных действий пользователя, что в применении к DVCS формируется в ожидание надёжного хранения всех действий с лёгкой возможностью возвращения старых данных.

Всё это есть в git. Пока ты не сделал git gc в рабочей копии - твои коммиты у тебя есть, даже если они не привязаны ни к одной ветке.

Как их вернуть? Я уже тебе говорил про ProGit и соответствующие маны.

Pinkbyte ★★★★★
()
Ответ на: комментарий от Pinkbyte

а всё что на сервере - херня

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

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

«После сборки доработать напильником»... Мне это стало надоедать ещё лет 15 назад.

А так ВНЕЗАПНО везде, то что тебя это достало никого не волнует. Есть reasonable default, он годится для большинства применений. Для эстетов - есть gitconfig.

Компьютер для разработчика, а не разработчик для компьютера.

Именно. 1 раз настроил - и забыл. На новом рабочем месте - развернул конфиги из бэкапа.

Pinkbyte ★★★★★
()
Ответ на: комментарий от Pinkbyte

Всё это есть в git. Пока ты не сделал git gc

Вот-вот. Пока одно и пока другое. И при этом глубоко спрятанное.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Pinkbyte

А так ВНЕЗАПНО везде, то что тебя это достало никого не волнует.

Ну так и меня не волнует, что там кого-то не волнует :) Я наткнулся на проблему, поинтересовался, почему так, вдруг я просто чего-то не понял. Разобравшись с причиной (да, действительно не понял, обманувшись в ожиданиях), осознал, что конкретный инструмент мне не подходит. А дальше — только отвечаю на встречные наезды :D Заметь, я нигде не говорю, что народ что-то там должен и т.п. Я только описал причины своего личного решения. Имею право. А что это кого-то может бесить — меня мало волнует :) Я пишу только за себя и за свои представления.

KRoN73 ★★★★★
() автор топика
Последнее исправление: KRoN73 (всего исправлений: 1)
Ответ на: комментарий от KRoN73

Вот этого и не должно быть в нормальной некрасноглазой DCVS

ЩИТО? А если на сервере реально херня и историю НАДО переписать? Я не имею ввиду какую-нибудь продакшен-ветку, я имею ввиду что кто-то закоммитил херню и хочет её изменить. Например ошибка в авторстве или в имени коммитера.

Если изменения уже на удалённом сервере, это твоя личная ветка и ты на 100% уверен что никто из нее не синкается, почему бы не переписать историю последнего коммита?

В противном случае, если есть хотя бы 1 пользователь кто синкает эту ветку - так лучше не делать. По понятным причинам - пользователю придется делать --force при pull, а это очень дурной тон.

Pinkbyte ★★★★★
()
Ответ на: комментарий от KRoN73

Разобравшись с причиной, понял, что инструмент мне не подходит. А дальше — только отвечаю на встречные наезды :D Заметь, я нигде не говорю, что народ что-то там должен и т.п. Я только описал причины своего личного решения. Имею право. А что это кого-то может бесить — меня мало волнует :) Я пишу только за себя и за свои представления.

А, ну извини, неправильно тебя понял. Я на тебя не наезжал, если что. Просто объясняю свою позицию, не более. Если тебе более удобен hg - ради Бога, замечательный инструмент, между прочим. Но у меня как-то не прижился, мне больше по душе git.

Pinkbyte ★★★★★
()
Ответ на: комментарий от Pinkbyte

А если на сервере реально херня и историю НАДО переписать?

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

vurdalak ★★★★★
()
Ответ на: комментарий от vurdalak

А потом мы внезапно обнаруживаем, что одна из VCS заявляет возможность сломать историю как фичу.

Как будто Mercurial этого не умеет, я тебя умоляю. ИМХО любая DVCS должна это уметь. Традиционным системам контроля версий это скорее вредно, нежели полезно. Но им это не сильно и надо, учитывая что у них ветвление как правило через жопу.

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

ЩИТО? А если на сервере реально херня и историю НАДО переписать?

А зачем? Чем тебе мешает история, если это уже именно история? У меня много херни в истории, только жить-то не мешает. Экономия на спичках в плане места на диске? Ну, в таком узком и запущенном случае, можно извратиться и почистить историю и в Mercurial. Но это очень редкая ситуация в моём представлении и операция изменения истории не должна быть столь простой и лёгкой.

я имею ввиду что кто-то закоммитил херню и хочет её изменить. Например ошибка в авторстве или в имени коммитера

Ну так изменил и закоммитил новую ревизию. Историю-то зачем менять?

Если изменения уже на удалённом сервере, это твоя личная ветка и ты на 100% уверен что никто из нее не синкается, почему бы не переписать историю последнего коммита?

Вот тут у нас концептуальное расхождение в понимании вопроса для чего нужна DVCS. Мне важно хранить именно всю историю. В том числе и моих глупостей. Даже доводилось несколько раз специально показывать исторические грабли.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Ну так изменил и закоммитил новую ревизию. Историю-то зачем менять?

Эээ, речь об авторстве коммита, это атрибут самого коммита, а не данные которые он вносит.

Pinkbyte ★★★★★
()
Ответ на: комментарий от Pinkbyte

Как будто Mercurial этого не умеет, я тебя умоляю

Разница в том, что в git, как оказывается, историю сломать легко по ошибке. А в hg это нужно делать специально и осознанно.

hg позволяет выстрелить себе в ногу, но защищает от выстрела в ногу, пока ты этого сам явно не хочешь. git позволяет выстрелить в ногу только из-за неверного понимания инструкции.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от vurdalak

А потом мы внезапно обнаруживаем, что одна из VCS заявляет возможность сломать историю как фичу.

не сломать, а отредактировать. причем hg это тоже позволяет, хотя и не так удобно/гибко, как git.

waker ★★★★★
()
Ответ на: комментарий от Pinkbyte

Как будто Mercurial этого не умеет, я тебя умоляю.

Там про плагин написано. Разве что amend доступен из коробки, тут согласен.

vurdalak ★★★★★
()
Ответ на: комментарий от waker

История — это список изменений. Если ты в список прошлых изменений вносишь правки, он уже перестаёт быть таковым и становится списком непонятно чего. Для меня это означает «сломать».

vurdalak ★★★★★
()
Ответ на: комментарий от KRoN73

Разница в том, что в git, как оказывается, историю сломать легко по ошибке.

Ээээммм, ну если указания атрибута --force - это случайность, ну я даже не знаю.

format C: случайно тоже набираете? А rm -rf / ? :-D

hg позволяет выстрелить себе в ногу, но защищает от выстрела в ногу, пока ты этого сам явно не хочешь. git позволяет выстрелить в ногу только из-за неверного понимания инструкции.

Это ж не дефолтное поведение, тебе же говорят - творится фигня, используй --force только если уверен что так надо. Ты не уверен и использовал --force - поздравляю, ты не читал того что тебе говорят и всё сломал.

Просто и понятно.

Pinkbyte ★★★★★
()
Ответ на: комментарий от KRoN73

Ну так изменил и закоммитил новую ревизию. Историю-то зачем менять?

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

waker ★★★★★
()
Ответ на: комментарий от Pinkbyte

Эээ, речь об авторстве коммита, это атрибут самого коммита

Противоречие какое-то в требованиях к пользователю. С одной стороны от пользователя git ожидается, что он будет достаточно дисциплинирован, ибо git достаточно мощный, чтобы позволять менять историю и т.п. С другой стороны, пользователь может осуществлять такую грубую ошибку, как коммит не под своим авторством? Даже странно выходит, как это я легко умудрился добавить ключик «-f», но за тысячи и тысячи коммитов ни разу не закоммитил от чужого имени. Более того, даже не представляю, как это сделать _по ошибке_ :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

А зачем? Чем тебе мешает история, если это уже именно история?

Представь, что к тебе в репозиторий один из твоих разработчиков по приколу закоммитит «контент, запрещённый на территории РФ» =).

Более реальный пример: проприетарный код, по ошибке попавший в «открытую версию». Про такую банальщину как пароли, ключи, etc. я вообще не говорю.

Deleted
()
Ответ на: комментарий от KRoN73

Разница в том, что в git, как оказывается, историю сломать легко по ошибке.

ее можно вернуть обратно примерно так же просто, как и «сломать». reflog в помощь.

waker ★★★★★
()
Ответ на: комментарий от vurdalak

История — это список изменений. Если ты в список прошлых изменений вносишь правки, он уже перестаёт быть таковым и становится списком непонятно чего.

Меня вот это тоже удивило, когда начал использовать гит. Как по мне, лучше иметь «кривую» историю, по которой можно отследить любое действие, чем «красивый» список непонятно чего.

orm-i-auga ★★★★★
()
Ответ на: комментарий от Pinkbyte

Ээээммм, ну если указания атрибута --force - это случайность, ну я даже не знаю.

Именно «-f» можно, действительно, случайно ввести. Скажем, у меня выработалась инстинктивная привычка вводить в «rm» ключики «-rf» только после имени каталога. Потому что пару раз были случаи, когда я введя что-то типа «rm -rf /usr» переключался в другую консоль, чтобы уточнить какие-то детали пути (при нехватке информации в случае автодополнения) и потом по возврату по той или иной причине нажимал Enter до введения остатка пути.

Так и тут, с «-f» можно и просто опечататься. Особенно, учитывая любовь git в обширным командам и ассортименту параметров.

Ну не должна, даже редкая ошибка, тем более, например, опечатка, влиять на столь важную для самой сути DVCS вещь, как история.

Ты не уверен и использовал --force - поздравляю, ты не читал того что тебе говорят и всё сломал.

Это и есть выстрел в ногу, когда ты этого выстрела не желаешь.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

С другой стороны, пользователь может осуществлять такую грубую ошибку, как коммит не под своим авторством?

В git'е «автор» и «коммитер» - это разные сущности. Автором может быть один человек, а коммитером - другой. Более того, это типично для крупных проектов, принимающих патчи от посторонних людей.

Deleted
()
Ответ на: комментарий от KRoN73

Ну так изменил и закоммитил новую ревизию. Историю-то зачем менять?

Ну, ё-моё! Ну объяснил же, что в гите нельзя поменять содержимое конкретного коммита, дерева или блоба. Ну сложно же понять?

Даже при git rebase старые коммиты никуда не деваются, единственное «но», в дефолтном воркфлоу на них не остаётся ссылок. Т.е. если хочешь хранить всю историю, то ставь ссылку на tip нужной ветки (тег или бранч) с названием «Извините, фигню сморозил», делай rebase, и история твоих фейлов никуда не исчезнет.

Запрети себе rebase. Издай политику, что тот кто хоть раз сделает рибейз, будет банально покаран перед строем...

Но мой личный опыт показывает: коммитим как можно чаще, а затем разбираемся с историей перед pull'ом.

Macil ★★★★★
()
Ответ на: комментарий от orm-i-auga

А ещё там кстати ветки удалять вроде можно. Я удивился, когда обсуждал с человеком гит, и он сказал что создаёт по 100500 веток и после мержа их удаляет. Нафига ветки тогда нужны вообще, я так и не понял.

vurdalak ★★★★★
()
Ответ на: комментарий от KRoN73

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

waker ★★★★★
()
Последнее исправление: waker (всего исправлений: 1)
Ответ на: комментарий от waker

давным давно видел такой пример: кто-то коммитит в репозиторий файл, выкладывает на публичный сервер, а потом оказывается что файл закопирайчен

Согласен. Потенциально — проблема, которую придётся решать в реальном мире изменением истории. Даже сам тему такую поднимал: Лицензированные материалы в DVCS. Правовые вопросы.

Но это редкая ситуация и должна решаться специальным способом, а не одиночными ключиками.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Про такую банальщину как пароли, ключи, etc. я вообще не говорю.

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

Про копирайт согласен, написал в предыдущем сообщении.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Про такую банальщину как пароли, ключи, etc. я вообще не говорю.

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

anonymous
()
Ответ на: комментарий от vurdalak

Нафига ветки тогда нужны вообще, я так и не понял.

Локальные ветки очень удобны для мелких фиксов. На каждый багрепорт/фикс - отдельная ветка. Когда приходит время отправлять код в основную ветку - он отправляется в master или другую «общую» ветку и локальная ветка сносится за ненадобностью.

Deleted
()
Ответ на: комментарий от waker

представь что у тебя есть приватный бренч в проекте, который никак нельзя пушать на сервер.

Представь, что у тебя под кроватью атомный реактор. Основываясь на этом, предлагаю законодательно закрепить обязательность ношения костюмов радиационной защиты.

// Я к тому, что это юзкейс какой-то марсианский.

vurdalak ★★★★★
()
Ответ на: комментарий от anonymous

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

Естественно, но и в репозитории им тоже делать нечего.

И кстати, ключи и пароли, закоммиченые в локальный репозиторий ещё не скомпрометированы. Их можно просто удалить из истории.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от waker

ее можно вернуть обратно примерно так же просто, как и «сломать». reflog в помощь.

Задача исправления истории — редакая и исключительная. Задача восстановления данных и лёгкого контроля всех изменений — частая. Поэтому DVCS в моём представлении должна быть сложной и защищённой от ошибок в плане редактирования истории и должна позволять без особых знаний и легко восстанвливать данные.

В git по факту получается, грохнуть данные легко, восстановить — сложно. В mercurial — наоборот, грохнуть сложно, восстановить легко. Поэтому для меня mercurial больше отвечает концепции DVCS (на всякий случай снова уточню, что это по-прежнему только личное мнение, нравится git — ради Бога, я просто пишу, почему не нравится лично мне).

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Но это редкая ситуация и должна решаться специальным способом, а не одиночными ключиками.

а она и не решается одиночными ключиками. для нее есть git-filter-branch и bfg. после них конечно надо делать push -f.

waker ★★★★★
()
Ответ на: комментарий от Deleted

Локальные ветки очень удобны для мелких фиксов.

Для мелких фиксов есть коммиты. Если тебе приходится откладывать одни фиксы до пуша и переключаться на другие, есть shelve/stash/как-там-его. А ветки как раз нужны для того, чтобы с ними могли работать разные разработчики, а потом мержить с основной веткой.

vurdalak ★★★★★
()
Ответ на: комментарий от orm-i-auga

История — это список изменений. Если ты в список прошлых изменений вносишь правки, он уже перестаёт быть таковым

Как по мне, лучше иметь «кривую» историю, по которой можно отследить любое действие, чем «красивый» список непонятно чего.

Ну, радует, что я не одинок со своим отношением к неприкосновенности истории :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Macil

Но мой личный опыт показывает: коммитим как можно чаще, а затем разбираемся с историей перед pull'ом.

Аналогично всегда стараюсь делать. Только в mercurial это делается точно также, как в git :) И не нужно ничего себе запрещать, настраивать, издавать политики... Просто берёшь и едешь.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от vurdalak

Для мелких фиксов есть коммиты. Если тебе приходится откладывать одни фиксы до пуша и переключаться на другие, есть shelve/stash/как-там-его.

Это просто разный workflow. Лично мне в гите удобно делать именно ветками. Кроме того, фикс - это не всегда один коммит, бывает и больше.

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

У нас тут DVCS, а не стопицотый клон CVSа. Ветки - это просто ветки. Как хочешь, так и юзай =).

Deleted
()
Ответ на: комментарий от waker

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

Я согласен, что в исключительных случаях редактирование истории может быть нужна. Но это именно исключительные случаи. Они не должны быть практикой и инструментарий для такого должен иметь надёжную защиту от случайных ошибок.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

От переписывания истории, что ты и сделал не застрахована ни одна DVCS, просто git не мешает тебе отпилить себе ногу, если ты очень этого хочешь. Не спорю, некоторые вещи в гите достаточно мутантские, но пользуясь им весьма активно уже лет 5-6, проблемы у меня возникали только при физическом повреждении метаданных репозитория.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Deleted

Кроме того, фикс - это не всегда один коммит, бывает и больше.

Я не очень понимаю, зачем это пушить именно в виде ветки. Если она сразу после пуша удаляется, какой в ней смысл? Почему нельзя запушиьть эти два коммита сразу в мастер?

vurdalak ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.