LINUX.ORG.RU

И снова на арене мы с git'ом...

 ,


0

1

Так и не понимаю я его логику. Хорошо ещё, что можно на кошках только тренироваться.

В общем, был у меня на GitHub'е репо с merge от 6-го июня:

*   commit 880bf16813a1c74d9e130b8506924c9e6e35c3a5
|\  Merge: 146eb59 d713363
| | Author: Balancer <balancer@balancer.ru>
| | Date:   Mon Jul 6 13:00:07 2015 +0300
| |
| |     Merge branch 'master' of git://github.com/Balancer/bors-3rd-jquery-wysibb
| |
| |     Conflicts:
| |             composer.json
| |
| * commit d713363404ec562d83aa0cd2279284d9af17163e
| | Author: Balancer <balancer@balancer.ru>
| | Date:   Sat Jul 4 20:05:05 2015 +0300
| |
| |     and libra
...
...
Плюс по крайней левой ветке оно ещё 6-го менялось.

Есть локальный репо. Х.з. уже что там за изменения, но небольшие. Bare. Пытаюсь синхронизировать с GitHub.

git fetch — всё прекрасно.

git push не лезет никак:

[rejected]        master -> master (non-fast-forward)

Смотрю по git log --graph --all — всё совпадает с тем, что на GitHub. Ну, полагаю, что HEAD не на ту ревизию показывает. Логику git понять так и не могу, поэтому гуглю. Естественно, многочисленные советы с «--force», наученный предыдущими опытами, пропускаю :)

Во, нахожу ещё один совет, как сменить HEAD. git push origin +master. Вроде, никаких --force, не должно быть ничего страшного? Выполняю. Ошибок нет. Всё коммитится. Смотрю в log --graph --all. Хм. Куда-то ромб с merge пропал. Лезу на github... Опаньки, было 22 коммита, показывается 20. И, да, коммиты от 6-го исчезли o_O

Ну, вот, вопрос. Как надо было поступить и как теперь вернуть последние изменения?

★★★★★

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

Это ты счас опечатался?

Да, само собой :) В hg нету fetch ;)

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

Non fast forward означает, что просто добавлением коммитов две истории не синхронизировать. Т.е. например на одном компе из коммита А коммит Б, а на другой из А В.можно сказать git push origin +master, чтобы форсированно привести ветку на сервере к текущему виду.

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

Non fast forward означает, что просто добавлением коммитов две истории не синхронизировать

Но fetch же проходит нормально? Никаких предупреждений нет. log --graph --all не показывает никаких проблем в структуре. Что не так?

Т.е. например на одном компе из коммита А коммит Б, а на другой из А В.

Ну так будет простое дерево коммитов. Делаем потом merge для Б и В и получаем снова одно состояние. Что и было проделано 6-го июня.

можно сказать git push origin +master, чтобы форсированно привести ветку на сервере к текущему виду

У меня локально и на сервере были коммиты от 6 июня. После git push origin +master они исчезли и на сервере, и локально. Что я делал не так, и как вернуть коммиты от 6-го :)

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

git fetch origin

git merge origin/master

git checkout master

git merge branch

git push origin master

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

Что я делал не так, и как вернуть коммиты от 6-го :)

git reflog — показывает все коммиты, накоторых побывал HEAD.

anonymous
()

github ничем не отличается от любой другой репы

склонируй локально и попробуй синхронизировать, а потом уже запушить

схема такая:

git commit

git pull

разрешение конфликтов

git commit

опять делаешь pull

и потом сразу push в репу

anonymous
()

Мне во всяких непонятных ситуациях помогает gitk --all. В ней лучше видно, что есть удалённо, а что локально.

sergej ★★★★★
()

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

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

Но fetch же проходит нормально?

Нормально, но локально получается например origin/master и просто master, надо сделать rebase (если хочется получить линейную историю) или merge(если хочется попроще). Т.е. делаем git merge origin/master из ветки master, пишем коммит, и отправляем на сервер новый мастер.

Ну так будет простое дерево коммитов. Делаем потом merge для Б и В и получаем снова одно состояние. Что и было проделано 6-го июня.

Ну да я это и писал :)

Что я делал не так

Надо смотреть графическое представление дерева, и какие коммиты мержились и где была текущая ветка (в каком коммите).

и как вернуть коммиты от 6-го :)

Спокойно, ничего не потерялось :) В папке .git есть лог текстовый, чтобы вернуть файлы, надо сделать git checkout $нужный_hash

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

git reflog — показывает все коммиты, накоторых побывал HEAD.

$ git reflog
d713363 HEAD@{0}: push
1802633 HEAD@{1}: push
db2caef HEAD@{2}: push
3a978e8 HEAD@{3}: push
18d677a HEAD@{4}: push
577762c HEAD@{5}: push
67a18c4 HEAD@{6}: push
44ae230

коммита 880-blah-blah не видно.

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

склонируй локально и попробуй синхронизировать, а потом уже запушить

Клон локальной репы ничем не отличается от локальной репы и от github'а. Всё также отсутствуют коммиты от 6 июня.

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

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

Аналогично, только Gogs :) GitLab крут, но уж очень тяжёл. А вот Gogs — изумителен, если нужна только репа (+issues). Сверхлёгкий, сверхбыстрый, крайне простой в установке.

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

что-то нахимичено

сделай на очередной копии:

git fsck

git gc

пару раз

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

Сколько работаю с джитом - ни разу не возникало проблем.

Попробуй для начала не трогать мастер-ветки.

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

Если тебя не затруднит, ответь, можно ли с Gogs делать следующее: держать master ветку на серваке, разработчики работают со своими локальными копиями в своих же ветках. Потом изменения в ветке пушатся на сервак и создается pull request. А потом с помощью веб-морды (на данный момент, Gitlab), делается merge этого добра в master ветку на серваке. Интересует функциональность из последнего предложения.

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

Да, это весьма опасно и поэтому говорю: на очередной копии, точнее копиях, не затрагивая поциентов.

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

Спокойно, ничего не потерялось :) В папке .git есть лог текстовый, чтобы вернуть файлы, надо сделать git checkout $нужный_hash

Последний правильный коммит был 880bf16813a1c74d9e130b8506924c9e6e35c3a5, это ещё в топикстарте я отметил :)

Нашёл его в logs/refs/remotes/origin/master.

Сделал checkout на клонированной копии — выругался про «You are in 'detached HEAD' state». Сделал -b fork получил новый бранч. Смержил с ним master, запушил всё в основной локальный репо, а потом и в github.

В результате там те же 22 коммита, что и были.

Нет, не понимаю я этой логики, когда коммиты могут то добавляться, то убираться... :) По мне, так коммит — это транзакция. Результат которой потом можно изменить, но не сам коммит. Не понимаю я этого переписывания истории :D

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

Не понимаю я этого переписывания истории :D

Так в крупных проектах никто историю никто не переписывает и не делает rebase. Даже когда руби зафакапились, коммит с троллингом никто не удалил.

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

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

Если тебя не затруднит, ответь, можно ли с Gogs делать следующее

Ломает с тестовым аккаунтом ковыряться. Я открыл регистрацию на http://git.home.balancer.ru/ — можешь сам пощупать. Только погда clone по ssh будешь делать, учти, что там порт не 22, а 30122. Я так и не понял, как прямо в git-запросе порт указывать, поэтому прописал в ~/.ssh/config:

Host gogs
    User        git
    HostName    home.balancer.ru
    Port        30122

А потом:

git clone git@gogs:balancer/test.git

...

Или можешь сразу выполнить:

mkdir -p /var/gogs

docker run --name gogs -d -p 30122:22 -p 3000:3000 -v /var/gogs:/data codeskyblue/docker-gogs

И оно у тебя появится доступное на 3000-м порту по http и 30122 по ssh. Пакет там мелкий совсем, ставится на раз.

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

Так в крупных проектах никто историю никто не переписывает

Всё равно стрёмно. Один плюсик — и на GitHub уже не тот master, с которым все работают, а непонятная хрень.

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

Всё равно стрёмно. Один плюсик — и на GitHub уже не тот master, с которым все работают, а непонятная хрень.

Ну не знаю, на битбакете в меркуреале можно не давать кому попало запись в дефолтную ветку, тут наверное тоже как-то это разруливается.

Да и за плюсик по башке давать надо, если больше одного человека работает над проектом

xorik ★★★★★
()

книжку то про гит прочитал?

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

Запрашивает пароль.
P.S. При git clone

Это значит, что порт неверный. Пропиши алиас в ~/.ssh/config, как я показал выше и по этому алиасу клон делай.

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

В этих ваших интернетах пишут, что pull request нет

Ну, нет, так нет :) Мне-то оно нужно только для локалхостового git'а.

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

Да и за плюсик по башке давать надо

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

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

Омг.

В git каждый репозиторий отдельно хранит свои ветки и точные копии веток с удалённых репозиториев (в отдельном неймспейсе). Так,

  • git log master — это обращение к «своей» ветке master;
  • git log origin/master — это обращение к локальной копии ветки master из удалённого репозитория origin.

git fetch обновляет только последние. В то время как git pull — это git fetch + git merge в текущую ветку из «привязанной» к ней удалённой ветки. Например,

git checkout master
git pull

эквивалентно (со структурой репозитория по умолчанию)

git checkout master
git fetch
git merge origin/master

В твоём же случае ты сделал только fetch. Твоя ветка master осталась неизменной. Ну и понятно, что при попытке запушить локальную ветку master на сервер было сказано, что состояние локальной ветки master не является потомком состояния ветки master на сервере (это определение «non-fast-forward»). Ты же проигнорировал предупреждение (как обычно) и вместо того, чтобы сделать слияние, форсировал замену состояния на сервере состоянием своего репозитория. Ясен хрен, с потерей данных.

Что делать: git reflog origin/master на том репозитории, где был сделан fetch, в списке ревизий найти потерянную (она, скорее всего, будет второй сверху) и сделать git push -f origin <найденная-ревизия>:master.

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

от которой так легко получить неожиданное поведение.

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

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

Что, опять на SO push -f подсунули ? :)

// git не осилил от слова совсем, катаюсь на hg

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

Давай ты ещё пожалуешься на rm -rf

Нет, не давай. Задача rm — удалять файлы. Задача VCS — хранить историю.

Плюсик — это полный аналог ключа -f

:facepalm:

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

А, это bare. Тьфу, проглядел, сорри.

Впрочем, мало что меняется. Удалённых веток (origin/*) у нас нет, но fetch всё равно не перезаписывает «собственные» ветки. Вместо этого по умолчанию фетчится либо дефолтная ветка (удалённый HEAD), либо что-указано, и хэши всего, что сфетчено, кладутся в FETCH_HEAD. Всё. Дальнейшие действия на усмотрение оператора или скрипта.

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

Что полностью, целиком, абсолютно эквивалентно

Вранье. С -f ты можешь (случайно) переписать несколько веток, с + - не можешь.

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

Забыл дописать «в случае изменения одной ветки». Так-то да, -f глобально, а + действует на данный конкретный refspec.

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

Крон, блин, ты вроде мужик не тупой, но тупишь... Давно пора понять, что у git своя идеология, свой стиль работы. Его нужно понять. Для этого достаточно прочитать https://git-scm.com/book/en/v2 первые 3 главы. И понять их (с первого раза может не получиться). Схожи почитай, что-ли. Не будешь портить свой репозиторий и тут глупости писать.

git push origin +master. Вроде, никаких --force

Это одно и то же. «+» перед веткой и --force.

git fetch — всё прекрасно.
git push не лезет никак

После fetch нужно руками сделать либо merge либо rebase, что тебе больше нравится. Либо делать pull и указывать --rebase или --merge (по умолчанию).

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

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

Давно пора понять, что у git своя идеология, свой стиль работы

Я это давно понял. Потому и говорю, что не укладывается его идеология у меня в голове :)

Для этого достаточно прочитать

Для меня — недостаточно. Я смысла в белом шуме, наверное, не меньше найду :)

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