• Как разрешить merge конфликт?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    git checkout master
    git pull origin
    git checkout branch-b
    git merge master

    Это всё можно заменить одной командой
    git pull origin master

    В этот момент процесс останавливается на моменте создания коммита слияния и вам нужно используя свой текстовый редактор разрешить все конфликты. Но гораздо эффективнее использовать инструменты разрешения конфликтов встроенные в графические Git-клиенты (рекомендую SmartGit либо IDE от JetBrains)

    Далее завершаем слияние
    git add .
    git push origin

    Тут вы забыли про git commit и указывать origin это лишнее, так как у вас ветка уже связана с вышестоящей. Но на самом деле достаточно всего одной команды для завершения
    git merge --continue
    git push # ну и отправить результат
    Ответ написан
    Комментировать
  • Почему файл не добавляется в центральный репозиторий?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Чтобы файл оказался во внешнем репозитории, его следует сначала закоммитить, чтобы он попал в локальный репозиторий. А уже после пуша новых коммитов, вы увидите изменения на гитхабе. Что за ошибка при аутентификации через терминал — это уже другой интересный вопрос.
    Ответ написан
    Комментировать
  • Как собрать коммиты из 2-х разных локальных репозиториев в последовательную историю?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    git checkout --orphan second
    git pull second second # во второй репе ветка называется second
    git switch master
    git merge second --allow-unrelated-histories
    # решаю конфликты

    Эти манипуляции можно заменить одной командой
    git pull second second --allow-unrelated-histories
    Результат будет идентичный.

    хочу указать у коммита 0f6a3f0 родительским коммитом d5c58d8

    Коммиты в гите неизменяемы. Если изначально родителя не было, то вы не прицепите его постфактум. Но вы можете пересадить ветку second на вершину master, пересобрав коммиты заново.

    Чтобы получить что вам хочется, следует действовать иначе:
    git fetch second # скачать все коммиты из второго репо
    git switch second # перейти в ветку second
    git rebase master # пересобрать ветку second с вершины ветки master
      dropping 0f6a3f0 third, "two" -- patch contents already upstream
      Successfully rebased and updated refs/heads/second.
    git switch master # вернуться в master
    git merge second --no-ff # влить second в master

    Получим:
    git log --oneline --graph
    *   13dddb5 (HEAD -> master) Merge branch 'second'
    |\
    | * 515f80e (second) fourth, "three"
    |/
    * d5c58d8 second, "two"
    * fcc376b first, "one"

    Коммит third, "two" исчез из истории (дропнут) во время rebase, так как он полностью повторяет состояние second, "two"

    Но если вам надо действительно последовательную историю, то не надо создавать коммит слияния. Не используйте ключ --no-ff в последней команде. Это просто установит указатель master на вершину.
    И получится линейная история
    git log --oneline --graph
    * 515f80e (HEAD -> master, second) fourth, "three"
    * d5c58d8 second, "two"
    * fcc376b first, "one"
    Ответ написан
  • Как в TortoiseGit залить в ветку контент другой ветки, избежав всех конфликтов и потери истории?

    sergey-kuznetsov
    @sergey-kuznetsov
    Автоматизатор
    GUI-клиенты удобны и ими стоит пользоваться. Но проблема в том, что не всё, что можно сделать в консоли, доступно в графических интерфейсах. Некоторые операции, особенно низкоуровневые, делаются исключительно через терминал и нет никаких причин выдумывать графический интерфейс для них.

    Можно ли это сделать через TortoiseGit?

    Нет, не получится. Извините, но TortoiseGit один из самых ущербных клиентов, которые я видел. Он не умеет практически ничего. Максимальный функционал реализован в SmartGit и ещё в средах разработки от JetBrains.
    Ответ написан
    2 комментария
  • Как правильно слить воедино нескольких репозиториев в Git?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Вы перепутали команду. Слияние делается не через Checkout, а через Merge. И предварительно, через filter-repo, нужно подчистить и реорганизовать тот репозиторий, откуда хотите сливать недостающее, чтобы оставить только нужное и в правильном каталоге.
    Ответ написан
    Комментировать
  • Как создать вложенную ветку в Git?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Это не «вложенная» ветка, это у вас получится обычная ветка со слешем в названии.

    Внутри себя гит использует использует файлы для запоминания веток. Имя файла совпадает с названием ветки, а содержимое файла содержит хэш последнего коммита ветки. Но если в названии есть слеши, то левая часть будет уже каталогом. А в файловой системе нельзя создать в одном месте файл и каталог с одним и тем же названием, вот гит вам и говорит, что нельзя создать такой путь.
    Ответ написан
    Комментировать
  • Как затягивать изменения с сервера через Git?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Этот мануал в вашем случае не подходит. Там синхронизация односторонняя. Вы отправляете не на сайт, а в репозиторий на сервере. Затем хук извлекает содержимое ветки master в каталог с файлами сайта, затирая всё что там ранее мог изменить пользователь через админку.

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

    если нажать pull или fetch all, то локальная версия изменений на сервере не видит.

    А разве должен видеть? Fetch/Pull скачивает не файлы из рабочего каталога, а коммиты из репозитория. Это вообще разные сущности. Чтобы в репо попали изменения, их нужно коммитить, только так и не иначе.

    Предлагаю не создавать bare-репозиторий без рабочего каталога, а инициализировать обычный репо прямо в каталоге сайта. Обновления не проталкивать через push, а забирать через pull, потому что гит не сможет отправить push в текущую ветку. Чтобы забрать изменения файлов с сервера, их нужно предварительно коммитить разумеется, так как pull скачивает не файлы, а коммиты. Pull лучше делать на чистом от изменений рабочем каталоге, поэтому можно запускать простой скрипт
    git fetch # скачать обновления заранее, чтобы не ждать во время обновления файлов
    git stash # временно спрятать локальные правки
    git pull # применить обновления к сайту
    git stash pop # вернуть локальные правки обратно
    Это немного помогает избежать конфликтов между вашими локальными изменениями и изменениями из внешнего репозитория. Но лучше предварительно закоммитить изменения на сервере и перенести их на рабочий компьютер.

    Я таким способом в своё время успешно синхронизировал правки между компьютером разработки и основным сервером, где работал продукт. Там тоже часть файлов изменялось сервером во время работы. Скрипт отрабатывает достаточно быстро, чтобы сервер не успел заметить откат файлов при stash.
    Ответ написан
  • Как отменять коммит слияния, чтобы потом без проблем выполнить повторное слияние?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Линус Торвальдс уже подробно комментировал подобную ситуацию.

    И вы совершенно правильно всё поняли. Реверс коммита слияния восстанавливает код, который был изменён этим коммитом, но ничего не делает с эффектами, которые это слияние оказало на историю. Слияние всё ещё будет существовать, и оно всё ещё будет восприниматься как объединение двух веток, и будущие слияния будут воспринимать это слияние как последнее общее состояние — и реверт никак на это не повлияет.

    Таким образом, «revert» отменяет изменения кода, но это совсем не «undo» в том смысле, что он не отменяет влияния коммита слияния на историю репозитория.

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

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

    Давайте вернемся к вашей ситуации:
     P---o---o---M---x---x---W---x
      \         /
       A---B---C----------------D---E   <-- доработанная ветка задачи

    Где M — это слияние, которое вносит эти преждевременные изменения в основную ветку, x — это изменения не связанные с тем, что сделала тематическая ветка и уже внесённые в основную, а W - это «реверт M» (разве W не выглядит как перевернутое M?)

    Мы можем пересобрать тематическую ветку заново

    $ git rebase --no-ff P

    Получим:
       A'---B'---C'------------D'---E'  <-- пересозданная тематическая ветка
      /
     P---o---o---M---x---x---W---x
      \         /
       A---B---C----------------D---E

    Теперь можно слить пересозданную ветку с основной, не откатывая коммит W, и история основной ветки будет выглядеть так:
       A'---B'---C'------------D'---E'
      /                              \
     P---o---o---M---x---x---W---x---M2
      \         /
       A---B---C

    Правда такой трюк не сработает, если вы успели до слияния пообновлять тематическую ветку из основной. Эти коммиты слияния намертво свяжут две цепочки коммитов и не дадут сделать rebase.

    Но если обсуждать именно грамотный способ работы, то не стоит возвращаться в тематическую ветку после того, как она уже слита с основной. Ветка задачи всегда удаляется сразу после слияния, а все доработки и исправления делаются уже в новой ветке, как правильно заметил Дмитрий Гординский в соседнем ответе.
    Ответ написан
    Комментировать
  • Почему не могу закоммитить?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    первый раз работаю с git

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

    выдает 10000 файлов в каталоге

    Причина проста — вы инициализировали репозиторий находясь в корне вашего домашнего каталога. Нельзя так делать, если не хотите потерять свои файлы, бездумно вбивая команды типа stash.

    Что мне делать

    Удалить (или переименовать) подкаталог .git в котором хранится репозиторий. Затем создать его в правильном месте — в каталоге вашего проекта.
    Ответ написан
    Комментировать
  • Как спрятать файлы через gitignore, чтобы заходя в мой репозиторий не видели файлы проекта но могли открыть проект (сайт) по ссылке?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Изначально непонятно, почему вы хотите, чтобы точка входа на ваш сайт была в описании репозитория на GitHub, почему не сразу на GitHub Pages?

    Как можно сделать так, чтобы человек заходил в мой профиль гитхаба и видел в репозитории проекта «Мой сайт» только README-файл?

    Когда кто-то заходит в ваш репозиторий, то он видит содержимое вашей ветки по-умолчанию. Скрыть файлы из ветки нельзя, если они там реально есть.
    Вы можете создать ещё одну ветку, поместить в неё только файл Readme и сделать её основной. Либо публиковать ваш сайт из ветки gh-pages, а в ветке main удалить всё что вы не хотите показывать. В любом случае люди смогут выбрать любую ветку вручную и посмотреть все что там есть сейчас, либо было когда-либо раньше. Так как репозиторий помнит всё.

    Как спрятать файлы через gitignore

    Что делает файл gitignore?
    Файл gitignore помогает не добавить случайно файл в репозиторий. Он действует только на ещё неотслеживаемые файлы в рабочем каталоге. Если файл уже в репозитории, то совершенно не важно, что у вас прописано в игноре. И даже если файл есть в игноре, это всё равно не помешает нам добавить его в репо, при желании.

    Что не умеет делать файл gitignore?
    Добавление файла в игнор точно не удалит файл из репозитория, и даже не сделает его невидимым.
    Ответ написан
    Комментировать
  • Как исправить HEAD detached?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    У вас проблемы с пониманием того, что такое указатель HEAD.

    в новой ветке будет правильно установлено положение HEAD

    установить в ветке main ту же позицию HEAD, что и в ветке temp

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

    Обычно указатель HEAD ссылается на ветку, но если по ошибке, вместо reset использовать checkout на произвольный коммит, то указатель HEAD станет ссылаться на этот коммит, а не на ветку. Мы как бы выходим из ветки в никуда. Это состояние называется detached HEAD.
    Ответ написан
    4 комментария
  • Почему не получается объединить коммиты?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Вы сами процитировали причину:

    Нельзя начать пересборку ветки (cannot rebase), пока есть незакоммиченные изменения в рабочем каталоге (You have unstaged changes).

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

    Поэтому гит предлагает закоммитить или спрятать несохраненное (Please commit or stash them)

    Команда git stash по факту тоже создает коммит, но он не привязан ни к какой ветке и рабочий каталог становится чистым. Затем вы делаете свои нехорошие дела и восстанавливаете stash обратно в рабочий каталог.
    Ответ написан
    Комментировать
  • Как перенести git репозиторий из git/ в git/src/?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Можно конечно просто убрать их отслеживание через gitignore

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

    Как сделать это, не удаляя репозиторий на удаленном сервере?

    Если вам так важно именно «неудаление» то совет Виктора подойдет. Переместите .git в подкаталог src/ и гит будет считать что все файлы из корны проекта исчезли а содержимое каталога src переместилось в корень. Останется только закоммитить эти перемещения и удаления. Все старые файлы при этом останутся в истории проекта.

    Если вам не важна история, то проще удалить репозиторий и создать новый в src. Так вы избавитесь от мусора.

    Есть более красивое решение, когда сохранится вся история проекта, но выглядеть это будет как если бы вы изначально создали репо в каталоге src. Но по факту, тоже будет создан новый репозиторий.
    Ответ написан
    Комментировать
  • Как выполнить команды гита для вложенного репозитория?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Команды гита уже всегда применяются к текущему вложенному репозиторию. Но если выполнить команду git init внутри рабочего каталога существующего репозитория, то ничего не произойдет. Так что скорее всего эти вложенные репозитории у вас не создались.

    Если инициализировать репозиторий в другой папке где-то вовне репозитория, а потом её перенести внутрь project, тогда получите желаемое.

    Но общий репозиторий будет игнорировать подкаталог вложенного репозитория. Это для вас наверное станет неожиданностью тоже.
    Ответ написан
    Комментировать
  • Как удалить аккаунт из списка Contributors?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега GitHub
    Автоматизатор
    Если в истории проекта есть коммиты этого человека, то мы увидим его в списке Contributors — тех авторов коммитов, кто внес свой вклад в проект.
    Имена авторов коммитов берутся из подписей коммитов и не всегда их можно сопоставить с конкретными аккаунтами гитхаба, так как люди не удосуживаются настроить подпись, а на гитхабе вообще скрывают своё мыло. В итоге не попадают в список авторов и их работа остаётся анонимной.

    Пытаться удалять человека из авторов (забывать его вклад) нет смысла. Достаточно забрать права на изменения, или вообще удалить из списка Collabolators.
    Ответ написан
    2 комментария
  • Есть ли возможность в WebStorm, при разрешении гит-конфликтов, применить все изменения из левой части?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Такая возможность есть на предыдущем шаге, когда показывается список конфликтующих файлов.
    Кнопка Accept Theirs делает то, что вы хотите, но лучше так не делать а руками разруливать каждый конфликтующий блок кода. Иначе получите кашу, а не рабочий код.
    Ответ написан
  • Какой принцип работы с Git с нескольких компов?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Объясните, плиз, в двух словах

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

    Основная задача, чтобы на гитхабе был основной репозиторий

    Все репозитории на самом деле равноправны и вы можете любой из них объявить «главным», если хочется. Это вообще не важно.

    На остальных компах такие же настройки сделать?

    Эти настройки задают подпись, которая поставится на новых коммитах. Следовательно настроить подпись вы должны везде, где будете коммитить. В том числе и на гитхабе надо настроить эту подпись. Но так как там у вас нет доступа к командной строке, то настраивается через веб-интерфейс:

    65f132556ec1d868456092.png

    Или сделать на каждом компе имя типа MyName_COMP1?

    Вы хотите сохранять информацию о том, на каком компе создан коммит? Что это вам даст?

    для компов репозиторий на гитхабе является remote или origin?

    Репозиторий с которым вы работаете на текущем компе, является локальным. Все остальные по отношению к нему будут называться внешними (или удаленными, по-английски — remote). Ссылку на внешний репозиторий обычно запоминают в специальной переменной. Как правило используется связь с одним внешним репозиторием и принято называть эту remote-переменную origin. Но это имя может быть абсолютно любым, особенно если внешних репозиториев подключено несколько. Например вы можете вообще не использовать гитхаб, а обмениваться коммитами между компами напрямую. Ваш локальный репозиторий на одном компе станет внешним для другого репозитория на соседнем компе. Всё относительно.
    Ответ написан
    Комментировать
  • Как решить проблему при проверке статуса Git в терминале VSCode?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Работу в VSCode начинайте с команды Открыть каталог, чтобы этот каталог стал текущим для встроенного терминала. В противном случае ваш терминал открывается в домашнем каталоге и вы в этом каталоге зачем-то инициализировали репозиторий.

    Чтобы исправить ошибку, удалите этот репозиторий
    rm -rf "~/.git"
    И создайте репозиторий заново в правильном месте — в каталоге вашего проекта.
    Ответ написан
    Комментировать
  • Можно ли сделать git merge, чтобы в главной ветке появился только коммит слияния?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    При обычном merge как раз и создаётся один коммит слияния. Но, так как у него несколько родителей, то вы будете видеть и все коммиты тематической ветки в вашей основной ветке после слияния.

    То, что вы описали, называется squash-коммттом. Это когда все коммиты тематической ветки склеиваются в один, и этот коммит добавляется в конец основной ветки, без сохранения связи с исходной тематической веткой. Это проще всего делать в момент слияния вашего Pull Request на GitHub. Выбирайте там метод слияния Squash and Merge.
    Ответ написан
    Комментировать
  • Как настроить правила gitignore от обратного?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    В корне проекта создайте такой .gitignore
    # Игнорировать все файлы и папки в корне проекта
    /*
    
    # Не игнорировать папку src и сам этот gitignore
    !/src/
    !.gitignore
    
    # Игнорировать содержимое папки controllers
    /src/controllers/*
    
    # Кроме одного файла
    !/src/controllers/controller.env
    
    # Игнорировать содержимое папки users
    /src/users/*
    
    # Кроме одного файла
    !/src/users/users.env


    Чтобы я мог клонировать в app отдельный репозиторий и гит всего проекта не следил за гитом этого мини-репозитория

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

    просто само наличие папки с таким названием при клонировании

    Так и получится. При клонировании создастся пустая папка app. И её содержимое продолжит игнорироваться, даже без наличия вложенного репозитория.
    Ответ написан
    Комментировать