Разное

Git origin master push: linux — Difference between origin master & origin/master with git pull and git push commands

Переписывание истории репозитория кода, или почему иногда можно git push -f

Одно из первых наставлений, которое молодой падаван получает вместе с доступом к git-репозиториям, звучит так: «никогда не ешь жёлтый снег делай git push -f». Поскольку это одна из сотен максим, которые нужно усвоить начинающему инженеру-разработчику ПО, никто не тратит время на уточнение, почему именно так нельзя делать. Это как младенцы и огонь: «спички детям не игрушки» и баста. Но мы растём и развиваемся как люди и как профессионалы, и однажды вопрос «а почему, собственно?» встаёт в полный рост. Эта статья написана по мотивам нашего внутреннего митапа, на тему: «Когда можно и нужно переписывать историю коммитов».

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

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

На самом низком уровне git-репо представляет собой набор объектов и указателей на них. Каждый объект имеет свой уникальный 40-значный хэш (20 байт, записанные в 16-ричной системе), который вычисляется на основе содержимого объекта.

Иллюстрация взята из The Git Community Book

Основные типы объектов — это blob (просто содержимое файла), tree (набор указателей на blobs и другие trees) и commit. Объект типа commit представляет собой только указатель на tree, на предыдущий коммит и служебную информацию: дата/время, автор и комментарий.

Где здесь ветки и тэги, которыми мы привыкли оперировать? А они не являются объектами, они являются просто указателями: ветка указывает на последний коммит в ней, тэг — на произвольный коммит в репо. То есть когда мы в IDE или GUI-клиенте видим красиво нарисованные веточки с кружочками-коммитами на них — они строятся на лету, пробегая по цепочкам коммитов от концов веток вниз к «корню». Самый первый коммит в репо не имеет предыдущего, вместо указателя там null.

Важный для понимания момент: один и тот же коммит может фигурировать в нескольких ветках одновременно. Коммиты не копируются при создании новой ветки, она просто начинает «расти» с того места, где был HEAD в момент отдачи команды git checkout -b <branch-name>.

Итак, почему же переписывание истории репозитория вредно?

Во-первых, и это очевидно, при загрузке новой истории в репозитории, с которым работает команда инженеров, другие люди могут просто потерять свои изменения. Команда git push -f удаляет из ветки на сервере все коммиты, которых нет в локальной версии, и записывает новые.

Почему-то мало кто знает, что довольно давно у команды git push существует «безопасный» ключ --force-with-lease, который заставляет команду завершиться с ошибкой, если в удалённом репозитории есть коммиты, добавленные другими пользователями. Я всегда рекомендую использовать его вместо -f/--force.

Вторая причина, по которой команда git push -f считается вредной, заключается в том, что при попытке слияния (merge) ветки с переписанной историей с ветками, где она сохранилась (точнее, сохранились коммиты, удалённые из переписанной истории), мы получим адское число конфликтов (по числу коммитов, собственно). На это есть простой ответ: если аккуратно соблюдать Gitflow или Gitlab Flow, то такие ситуации, скорее всего, даже не возникнут.

И наконец есть неприятная побочка переписывания истории: те коммиты, которые как бы удаляются при этом из ветки, на самом деле, никуда не исчезают и просто остаются навечно висеть в репо. Мелочь, но неприятно. К счастью, эту проблему разработчики git тоже предусмотрели, введя команду сборки мусора git gc --prune. Большинство git-хостингов, как минимум GitHub и GitLab, время от времени производят эту операцию в фоне.

Итак, развеяв опасения перед изменением истории репозитория, можно, наконец, перейти к главному вопросу: зачем оно нужно и когда оправдано?

На самом деле, я уверен, что практически каждый из более-менее активных пользователей git хоть раз, да изменял историю, когда вдруг оказывалось, что в последнем коммите что-то пошло не так: вкралась досадная опечатка в код, сделал коммит не от того пользователя (с личного e-mail вместо рабочего или наоборот), забыл добавить новый файл (если вы, как я, любите пользоваться git commit -a). Даже изменение описания коммита приводит к необходимости его перезаписи, ведь хэш считается и от описания тоже!

Но это тривиальный случай. Давайте рассмотрим более интересные.

Допустим, вы сделали большую фичу, которую пилили несколько дней, отсылая ежедневно результаты работы в репозиторий на сервере (4-5 коммитов), и отправили свои изменения на ревью. Двое-трое неутомимых ревьюверов закидали вас крупными и мелкими рекомендациями правок, а то и вовсе нашли косяки (ещё 4-5 коммитов). Затем QA нашли несколько краевых случаев, тоже требующих исправлений (ещё 2-3 коммита). И наконец при интеграции выяснились какие-то несовместимости или попадали автотесты, которые тоже надо пофиксить.

Если теперь нажать, не глядя, кнопку Merge, то в главную ветку (у многих она по старинке называется master) вольются полтора десятка коммитов типа «My feature, day 1», «Day 2», «Fix tests», «Fix review» и т.д. От этого, конечно, помогает режим squash, который сейчас есть и в GitHub, и в GitLab, но с ним надо быть осторожными: во-первых, он может заменить описание коммита на что-то непредсказуемое, а во-вторых — заменить автора фичи на того, кто нажал кнопку Merge (у нас это вообще робот, помогающий релиз-инженеру собрать сегодняшний деплой). Поэтому самым простым будет перед окончательной интеграцией в релиз схлопнуть все коммиты ветки в один при помощи git rebase.

Но бывает также, что к код-ревью вы уже подошли с историей репо, напоминающей салат «Оливье». Такое бывает, если фича пилилась несколько недель, ибо была плохо декомпозирована или, хотя за это в приличных коллективах бьют канделябром, требования изменились в процессе разработки. Вот, например, реальный merge request, который приехал ко мне на ревью две недели назад:

У меня рука машинально потянулась к кнопке «Report abuse», потому что как ещё можно охарактеризовать реквест из 50 коммитов с почти 2000 изменённых строк? И как его, спрашивается, ревьюить?

Честно говоря, у меня ушло два дня просто на то, чтобы заставить себя приступить к этому ревью. И это нормальная реакция для инженера; кто-то в подобной ситуации, просто не глядя, жмёт Approve, понимая, что за разумное время всё равно не сможет сделать работу по обзору этого изменения с достаточным качеством.

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

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

Сделать это всё нам поможет всё тот же git rebase с ключом --interactive. В качестве параметра надо передать ему хэш коммита, начиная с которого нужно будет переписать историю. Если речь о последних 50 коммитах, как в примере на картинке, можно написать git rebase --interactive HEAD~50 (подставьте вместо “50” вашу цифру).

Кстати, если вы в процессе работы над задачей подливали к себе ветку master, то сначала надо будет сделать rebase на эту ветку, чтобы merge-коммиты и коммиты из мастера не путались у вас под ногами.

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

Иллюстрации взяты из книги Pro Git

Если изменения в C4 и C3 конфликтуют, то после разрешения конфликтов коммит C4 изменит своё содержание, поэтому он переименован на второй схеме в C4’.

Таким образом, вы получите ветку, состоящую только из ваших изменений, и растущую из вершины master. Само собой, master должен быть актуальным. Можно просто использовать версию с сервера: git pull --rebase origin/master (как известно, git pull равносилен git fetch && git merge, а ключ --rebase заставит git сделать rebase вместо merge).

Вернёмся наконец к git rebase --interactive. Его делали программисты для программистов, и понимая, какой стресс люди будут испытывать в процессе, постарались максимально сохранить нервы пользователя и избавить его от необходимости чрезмерно напрягаться. Вот что вы увидите на экране:

Это репозиторий популярного пакета Guzzle. Похоже, что rebase ему не помешал бы…


В текстовом редакторе открывается сформированный файл. Внизу вас ожидает подробная справка о том, что тут вообще делать. Далее в режиме простого редактирования вы решаете, что делать с коммитами в вашей ветке. Всё просто, как палка: pick — оставить как есть, reword — поменять описание коммита, squash — слить воедино с предыдущим (процесс работает снизу вверх, то есть предыдущий — это который строчкой ниже), drop — вообще удалить, edit — и это самое интересное — остановиться и замереть. После того, как git встретит команду edit, он встанет в позицию, когда изменения в коммите уже добавлены в режим staged. Вы можете поменять всё, что угодно в этом коммите, добавить поверх него ещё несколько, и после этого скомандовать git rebase --continue, чтобы продолжить процесс rebase.

Да, и кстати, вы можете поменять коммиты местами. Возможно, это создаст конфликты, но в целом процесс rebase редко обходится совсем уж без конфликтов. Как говорится, снявши голову, по волосам не плачут.

Если вы запутались и кажется, что всё пропало, у вас есть кнопка аварийного катапультирования git rebase --abort, которая немедленно вернёт всё как было.

Вы можете повторять rebase несколько раз, затрагивая только части истории, и оставляя остальные нетронутыми при помощи pick, придавая своей истории всё более и более законченный вид, как гончар кувшину. Хорошим тоном, как я уже написал выше, будет сделать так, что тесты в каждом коммите будут зелёными (для этого отлично помогает edit и на следующем проходе — squash).

Ещё одна фигура высшего пилотажа, полезная в случае, если надо несколько изменений в одном и том же файле разложить по разным коммитам — git add --patch. Она бывает полезна и сама по себе, но в сочетании с директивой edit она позволит вам разделить один коммит на несколько, причём сделать это на уровне отдельных строк, чего не позволяет, если я не ошибаюсь, ни один GUI-клиент и ни одна IDE.

Убедившись ещё раз, что всё в порядке, вы наконец можете со спокойной душой сделать то, с чего начался этот туториал: git push --force. Ой, то есть, разумеется, --force-with-lease!

Поначалу вы, скорее всего, будете тратить на этот процесс (включая первоначальный rebase на master) час, а то и два, если фича реально развесистая. Но даже это намного лучше, чем ждать два дня, когда ревьювер заставит себя наконец взяться за ваш реквест, и ещё пару дней, пока он сквозь него продерётся. В будущем же вы, скорее всего, будете укладываться в 30-40 минут. Особенно помогают в этом продукты линейки IntelliJ со встроенным инструментом разрешения конфликтов (full disclosure: компания FunCorp оплачивает эти продукты своим сотрудникам).

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

Спасибо за внимание всем, кто дочитал до конца! Надеюсь, что статья будет полезна не только вам, но и коллегам, которым ваш код попадает на ревью. Если у вас есть клёвые хаки для git — делитесь ими в комментариях!

Что именно делает «u»? «git push-U origin master» vs » git push origin master»

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

от kernel.org для git push:

— u

—set-upstream

для каждой ветви, которая обновлена или успешно нажата, добавьте ссылку вверх по течению(отслеживание), используемую без аргументов git-pull (1) и другими командами. Дополнительные сведения см. В разделе branch.<name>.merge в git-config (1).

здесь branch.<name>.merge С git config:

branch.<name>.merge

определяет, совместно с branch.<name>.remote, восходящая ветвь для данной ветви. Он сообщает git fetch/git pull, какую ветвь объединить, а также может повлиять на git push (см. push.неисполнение.) Когда в ветви <name>, он сообщает git fetch, что refspec по умолчанию будет отмечен для слияния в FETCH_HEAD. Значение обрабатывается как удаленная часть refspec и должно соответствовать ref, который извлекается из удаленного, заданного "branch.<name>.remote". Этот сведения о слиянии используются git pull (который сначала вызывает git fetch) для поиска ветви по умолчанию для слияния. Без этой опции git pull по умолчанию сливает первый извлеченный refspec. Укажите несколько значений, чтобы получить слияние осьминогов. Если вы хотите настроить git pull так, чтобы он сливался в <name> из другой ветки в локальном репозитории, вы можете указать branch.<name>.merge в нужную ветку, и используйте специальную настройку . (точка) для branch.<name>.remote.

я успешно настроил удаленный репозиторий с github, и я успешно нажал свою первую фиксацию на него с помощью:

git push -u origin master

затем я невольно успешно нажал свою вторую фиксацию в моем удаленном репозитории, используя:

git commit -m '[...]'

однако, неправильно думая, что мне придется снова нажать на origin С master, я побежал:

# note: no -u
git push origin master

что же делать? Казалось, это не произвело никакого эффекта. Разве я «отменял»git push -u origin master?

222

автор: ClosureCowboy

ключ «аргумент-менее git-pull». Когда вы делаете git pull из ветви, без указания источника удаленного или ветви, git смотрит на branch.<name>.merge настройка, чтобы знать, откуда тянуть. git push -u устанавливает эту информацию для ветви, которую вы нажимаете.

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

$ git checkout -b test

во-первых, мы нажимаем без -u:

$ git push origin test
$ git pull
You asked me to pull without telling me which branch you
want to merge with, and 'branch.test.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:

    [branch "test"]
    remote = <nickname>
    merge = <remote-ref>

    [remote "<nickname>"]
    url = <url>
    fetch = <refspec>

See git-config(1) for details.

теперь, если мы добавляем -u:

$ git push -u origin test
Branch test set up to track remote branch test from origin.
Everything up-to-date
$ git pull
Already up-to-date.

обратите внимание, что отслеживание информация была настроена так, что git pull работает, как ожидалось, без указания удаленного или ветви.

обновление: чаевые:

  • как Марк упоминает в комментарии, в дополнение к git pull этот параметр также влияет на поведение по умолчанию git push. Если вы привыкнете использовать -u чтобы захватить удаленную ветку, которую вы собираетесь отслеживать, я рекомендую установить ваш push.default значение config для upstream.
  • git push -u <remote> HEAD будет толкать текущая ветвь к ветви с тем же именем на <remote> (а также настроить отслеживание, чтобы вы могли сделать git push после этого).
git push -u origin master

— это то же, что:

git push origin master ; git branch --set-upstream master origin/master

сделать последнее заявление, если вы забыли -u!

или вы могли бы заставить его:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

если вы позволите команде сделать, если для вас она выберет ваши ошибки, как если бы вы набрали несуществующую ветку или вы не git remote add, хотя это может быть то, что вы хотите :).

в более простых терминах:

технически -u флаг добавляет ссылку отслеживания на вышестоящий сервер, на который вы нажимаете.

важно то, что это позволяет вам сделать git pull без предоставления дополнительных аргументов. Например, как только вы сделаете git push -u origin master можно назвать git pull и git будет знать, что вы на самом деле имели в виду git pull origin master.

в противном случае вам придется ввести всю команду.

4

автор: Adepoju Oluwasegun

все необходимые команды git bash, чтобы толкать и тянуть в Github:

git status 
git pull
git add filefullpath

git commit -m "comments for checkin file" 
git push origin branch/master
git remote -v 
git log -2 

Если вы хотите отредактировать файл тут:

edit filename.* 

чтобы увидеть все ветви и их коммиты:

git show-branch

-7

автор: Kamta Mishra

Что такое «git remote add …» и «git push origin master»?

Update: обратите внимание, что принятый в настоящее время ответ увековечивает распространенное заблуждение о поведении git push, который не был исправлен, несмотря на комментарий, указывающий на это.

ваше резюме того, что пульты дистанционного управления-как псевдоним для URL-адреса репозитория-правильно.

так почему же URL не git://[email protected]/peter/first_app.git но в другом синтаксисе — что это за синтаксис? Почему это должно закончиться? с.ГИТ? Я старался не использовать .git в конце, и это тоже работает. Если нет .ГИТ, что еще это может быть? Git у новичка, похоже, является учетной записью пользователя на сервере git?

два URL-адреса, которые вы упомянули, указывают, что должны использоваться два разных транспортных протокола. Тот, который начинается с git:// для протокола git, который обычно используется только для доступа только для чтения к репозиториям. Другой, [email protected]:peter/first_app.git, является одним из различных способов указания доступа к репозиторий по SSH-это «синтаксис стиля scp», описанный в документация. Что имя пользователя в синтаксисе стиля scp является git из — за того, как GitHub имеет дело с идентификацией пользователей-по существу, это имя пользователя игнорируется, и пользователь идентифицируется на основе пары ключей SSH, которую они использовали для аутентификации.

что касается многословия git push origin master, вы заметили, что после первого толчка, то вы можете просто сделать git push. Это из-за серия трудных для запоминания, но в целом полезных значений по умолчанию:)

  • если удаленный не указан, удаленный настроен для текущей ветви (в remote.master.url в вашем случае) используется. Если это не настроено, то это.
  • если нет «refspec» (например,master, master:my-experiment, etc.) указано, затем git по умолчанию нажимает каждую локальную ветвь, которая имеет то же имя, что и ветвь на удаленном компьютере. Если у вас просто есть ветка под названием master общего между репозиторий и удаленный, это будет то же самое, что и нажатие вашего master на пульт master.

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

git push origin master

… чтобы случайно не толкать другие ветки.


в ответ на ваши комментарии по одному из других ответов, это звучит для меня, как будто are изучение git сверху вниз очень эффективно — вы обнаружили, что значения по умолчанию работают, и ваш вопрос спрашивает, Почему 😉 чтобы быть более серьезным, git can использоваться по существу так же просто, как SVN, но зная немного о пультах и ветвях, вы можете использовать его гораздо более гибко, и это действительно может изменить способ работы к лучшему. Ваше замечание о семестровом курсе заставляет меня подумать о том, что сказал Скотт Чакон в интервью подкаста-студентов учат всем видам основных инструментов в информатике и разработка программного обеспечения, но очень редко контроль версий. Распределенные системы управления версиями, такие как git и Mercurial, теперь настолько важны и настолько гибки, что стоило бы преподавать курсы по ним, чтобы дать людям хорошее обоснование.

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

  • первичная документация для git так трудно разобрать для новичков. (Хотя я бы сказал, что если Вы Google для почти любого вопроса git, полезный учебный материал (или ответы переполнения стека :)) появляются в настоящее время.)
  • в git есть несколько странных поведений, которые трудно изменить сейчас, потому что многие сценарии могут полагаться на них, но запутывают людей.

Git push | Atlassian Git Tutorial

Команда git push используется для выгрузки содержимого локального репозитория в удаленный репозиторий. Она позволяет передать коммиты из локального репозитория в удаленный. Эта команда симметрична команде git fetch: при извлечении с помощью fetch коммиты импортируются в локальные ветки, а при публикации с помощью push коммиты экспортируются в удаленные ветки. Настроить удаленные ветки можно с помощью команды git remote. Команда push может перезаписать изменения, поэтому при ее использовании следует соблюдать осторожность. Эти проблемы обсуждаются ниже.

Использование git push

git push <remote> <branch>

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

git push <remote> --force

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

git push <remote> --all

Публикация всех локальных веток в указанном удаленном репозитории.

git push <remote> --tags

При публикации ветки или использовании опции --all теги не публикуются автоматически. Флаг --tags отправляет все локальные теги в удаленный репозиторий.

Обсуждение git push

Команда git push чаще всего используется для публикации выгружаемых локальных изменений в центральном репозитории. Для того чтобы поделиться изменениями, внесенными в локальный репозиторий, с удаленными участниками команды, необходимо выполнить команду push.

На рисунке выше показано, что происходит, когда ваша локальная ветка master изменяет предыдущие коммиты ветки master центрального репозитория и вы публикуете изменения с помощью команды git push origin master. Обратите внимание, что команда git push по сути аналогична команде git merge master, запущенной из удаленного репозитория.

Git push и синхронизация

Команда git push — это один из многих компонентов, которые используются в общем процессе синхронизации в Git. Команды синхронизации работают с удаленными ветками, которые настраиваются с помощью команды git remote. Команду git push можно рассматривать как команду «выгрузки», а команды git fetch и git pull — как команды «загрузки». После того как наборы изменений перемещены посредством «загрузки» или «выгрузки», в месте назначения можно интегрировать изменения, выполнив их слияние командой git merge.

Публикация в чистые репозитории

В настоящее время в качестве центрального исходного репозитория Git часто используют удаленно размещенный чистый (--bare) репозиторий. Этот исходный репозиторий размещается за пределами рабочего места у доверенной третьей стороны, например в Bitbucket. Поскольку при публикации нарушается структура удаленных веток, наиболее безопасный и распространенный вариант публикации — это публикация в репозиторий, созданный с флагом --bare. Чистые репозитории не имеют рабочего каталога, поэтому при публикации содержимое рабочего каталога не изменяется. Дополнительную информацию о создании чистых репозиториев см. в документации по команде git init.

Принудительная публикация

Git предотвращает перезапись истории центрального репозитория, отклоняя push-запросы, если нельзя выполнить их ускоренное слияние. Так, если история удаленного репозитория отличается от вашей истории, необходимо загрузить удаленную ветку командой pull и выполнить ее слияние с локальной веткой командой merge, а затем попробовать выполнить команду push еще раз. Это похоже на то, как в SVN необходимо синхронизироваться с центральным репозиторием с помощью команды svn update перед тем, как сделать коммит набора изменений.

Флаг --force отменяет это поведение и подгоняет ветку удаленного репозитория под вашу локальную ветку, удаляя любые вышестоящие изменения, которые могли быть внесены с момента последнего выполнения вами команды pull. Принудительное использование команды push оправдано лишь в том случае, когда вы понимаете, что только что опубликованные вами коммиты были не совсем правильными и вы исправили их с помощью команды git commit --amend или интерактивного перебазирования. При этом прежде, чем использовать опцию --force, вы должны быть абсолютно уверены в том, что никто из участников вашей команды не забирал эти коммиты с помощью команды pull.

Примеры

Команда git push по умолчанию

В следующем примере приведен один из стандартных методов публикации локальных вкладов в центральный репозиторий с помощью команды push. Сначала проверяется актуальность вашей локальной главной ветки путем извлечения копии центрального репозитория и перебазирования ваших изменений поверх них. Кроме того, интерактивное перебазирование — это хорошая возможность очистить ваши коммиты перед тем, как делиться ими. Затем все коммиты вашей локальной главной ветки отправляются в центральный репозиторий с помощью команды git push.

git checkout master
git fetch origin master
git rebase -i origin/master
# Squash commits, fix up commit messages etc.
git push origin master

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

Принудительная команда push при исправлении коммитов

Команда git commit имеет опцию --amend, которая позволяет обновить предыдущий коммит. В коммиты часто вносятся исправления, чтобы обновить сообщение коммита или добавить новые изменения. Если коммит был исправлен, то при выполнении команды git push произойдет сбой, так как Git воспримет исправленный и удаленный коммиты как разнородное содержимое. Опция --force позволит выполнить команду push и опубликовать измененный коммит.

# make changes to a repo and git add
git commit --amend
# update the existing commit message
git push --force origin master

В приведенном выше примере предполагается, что он выполняется в существующем репозитории с историей коммитов. Команда git commit --amend используется для обновления предыдущего коммита. Затем исправленный коммит принудительно публикуется с помощью команды push с опцией --force.

Стирание удаленной ветки или тега

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

git branch -D branch_name
git push origin :branch_name

Первая команда сотрет локальную ветку с именем branch_name. Если в команде git push перед именем ветки поставить двоеточие, будет стерта удаленная ветка.

Нужно ли запрещать git push origin master -f на уровне репозитория? — Хабр Q&A

В моей команде возникла жестка дискуссия о том нужно ли запрещать делать push’ы в мастера с ключем force на уровне репозитория.

Наш производственный процесс выглядит следующим образом. Когда девелопер берет себе очередной таск, он создает себе отдельную ветку, которая отбита от актуального мастера. Как только таск закончен у нас необходимо создать merge request, который должен просмотреть кто-то из команды. Если все в порядке, то ветка сливается с мастером и удаляется. Мы используем гитлаб, который позволяет слить ветку с мастером по одному клику.

Однажды в мастера попала ветка, которая там быть еще не должна. Так вышло, что висел merge request к которому были замечания, но человек, который просматривал код кликнул не в том месте, где нужно было и слил незаконченную ветку с мастером. Сразу же был сделан реверт, который по сути представляет собой коммит, уничтожающий предыдущий merge. Этот самый реверт спровоцировал пару проблем. В итоге было сделано следующее — этот самый случайный merge был «вырезан», после чего последовала страшная команда git push origin master --force-with-lease.

На мой взгляд данное решение было оправдано потому, что:

  1. В истории версий не будет мусора. Действительно — только что вошел merge по неосторожности, сверху на него упал реверс-коммит. Но через час, как только будут заимплементированы вещи, которые появились после ревью, будет сделан еще один merge с той лишь разницей, что он будет на несколько коммитов больше. В итоге имеем кучу ненужного в истории кода.
  2. В нашем конкретном случае если не вырезать неудачный merge, то в конечном итоге после имплементации замечаний пришлось бы делать rebase на актуального мастера (в котором уже был реверс-коммит) и это создало бы кучу конфликтов, которые пришлось бы развязывать.

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

Вопросы:

  1. Кто как считает — нужно ли отключать возможность push’а с форсом?
  2. Что у Вас делают если в мастера случайно попало что-то, чего там быть не должно?

Опасность git push —force и полезность git push —force-with-lease — urvanov.ru

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

Если вы поправили какие-нибудь старые коммиты в истории git, например: исправили имя автора или e-mail, или отменили последний коммит или воспользовались amend или revert, то при попытке push-а git справедливо «ругнётся»:

$ git push
To https://github.com/urvanov-ru/test0001.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to ‘https://github.com/urvanov-ru/test0001.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.

$ git push

To https://github.com/urvanov-ru/test0001.git

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

error: failed to push some refs to ‘https://github.com/urvanov-ru/test0001.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.

Чтобы нам всё же запушить наши изменения, нам нужно выполнить либо

git push —force origin <имя_ветки>

git push —force origin <имя_ветки>

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

git push —force-with-lease origin <имя_ветки>

git push —force-with-lease origin <имя_ветки>

Такой вариант лучше тем, что если кто-то успел запушить свои коммиты после того, как мы забирали изменения с сервера, то он не будет их перетирать, а выдаст нам ошибку, после чего мы сможем интегрировать чужие коммиты со своими изменениями и попытаться сделать
push —force-with-lease ещё раз.


Поделиться:

Git — книга

2-е издание (2014)

Загрузить электронную книгу

Вся книга Pro Git, написанная Скоттом Чаконом и Беном Штраубом и опубликованная Apress, доступна здесь. Все содержимое находится под лицензией Creative Commons Attribution Non Commercial Share Alike 3.0. Печатные версии книги доступны на Amazon.com.>

    1. 1.1
      О системе контроля версий
    2. 1.2
      Краткая история Git
    3. 1.3
      Основы Git
    4. 1.4
      Командная строка
    5. 1.5
      Установка Git
    6. 1.6
      Первоначальная настройка Git
    7. 1.7
      Как получить помощь?
    8. 1,8
      Заключение
    1. 2.1
      Создание Git-репозитория
    2. 2.2
      Запись изменений в репозиторий
    3. 2.3
      Просмотр истории коммитов
    4. 2.4
      Операции отмены
    5. 2,5
      Работа с удалёнными репозиториями
    6. 2,6
      Работа с метками
    7. 2,7
      Псевдонимы в Git
    8. 2,8
      Заключение
    1. 3.1
      О ветвлении в двух словах
    2. 3.2

.

Переписывание истории репозитория кода, или почему иногда можно git push -f

Одно из первых наставлений, которое молодой падаван получает вместе с доступом к git-репозиториям, звучит так: «никогда не ешь жёлтый снег делай git push -f ». Это одна из сотен максим, которые нужно усвоить начинающему инженеру-разработчику ПО, не тратит время на уточнение, почему именно так нельзя делать. Это как младенцы и огонь: «спички детям не игрушки» и баста.Но мы растём и развиваемся как люди и как профессионалы, и однажды вопрос «а почему, собственно?» встаёт в полный рост. Эта статья написана по мотивам нашего внутреннего митапа, на тему: «Когда можно и нужно переписывать историю коммитов».

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

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

На самом низком уровне git-репо представляет собой набор объектов и указателей на них. Каждый объект имеет свой уникальный 40-значный хэш (20 байт, записанные в 16-ричной системе), который вычисляется на основе содержимого объекта.

Иллюстрация взята из Книги сообщества Git

Основные типы объектов — это blob (просто содержимое файла), дерево (набор указателей на blob и другие деревья) и фиксация.Объект типа commit представляет собой только указатель на дерево, на предыдущий коммит и служебную информацию: дата / время, автор и комментарий.

Где здесь ветки и тэги, которые мы привыкли оперировать? А они не являются объектами, они являются указателями: ветка указывает на последний коммит в ней, тэг — на произвольный коммит в репо. То есть когда мы в IDE или GUI-клиенте красиво нарисованные веточки с кружочками-коммитами на них — они строятся на лету, пробегая по цепочкам коммитов от концов веток вниз к «корню».Самый первый коммит в репо не имеет предыдущего, вместо указателя там null.

Важный для понимания момент: один и тот же коммит может фигурировать в нескольких ветках одновременно. Коммиты не копируются при создании новой ветки, она просто начинает «расти» с того места, где был HEAD в момент отдачи команды git checkout -b <имя-ветки> .

Итак, почему же переписывание истории репозитория вредно?

Во-первых, и это очевидно, при загрузке новой истории в репозитории, с которыми работает команда инженеров, другие люди могут просто потерять свои изменения.Команда git push -f удаляет из ветки на сервере все коммиты, которых нет в локальной версии, и записывает новые.

Почему-то мало кто знает, что довольно давно у команды git push существует «безопасный» ключ --force-with-lease , который заставляет команду завершиться с ошибкой, если в удалённом репозитории есть коммиты, добавленные другими пользователями . Я всегда рекомендую использовать его вместо -f / - force .

Вторая причина, по которой команда git push -f считается вредной, заключается в том, что при попытке слияния (слияния) ветки с переписанной историей с ветками, где она сохранилась (точнее, сохранились коммиты, удаленные из переписанной истории), мыим адское число конфликтов (по сообществу коммитов, собственно).На это есть простой ответ: если аккуратно соблюдать Gitflow или Gitlab Flow, то такие ситуации, скорее всего, даже не возникнут.

И наконец есть неприятная побочка переписывания истории: те коммиты, которые как бы удаляются при этом из ветки, на самом деле, никуда не исчезают и просто остаются навечно висеть в репо. Мелочь, но неприятно. К счастью, эту проблему разработчики git тоже предоставили, введя команду сборки мусора git gc --prune . Большинство git-хостингов, как минимум GitHub и GitLab, время от времени производят операцию в фоне.

Итак, развеявение перед изменением истории репозитория, можно, наконец, перейти к главному вопросу: зачем оно нужно и когда оправдано?

На самом деле, я уверен, что практически каждый из более-менее активных пользователей git хоть раз, да изменил историю, когда вдруг оказывалось, что в последнем коммите что-то пошло не так: вкралась досадная опечатка в код, сделал коммит не от того пользователя (с личным e-mail вместо рабочего или наоборот), забыл добавить новый файл (если вы, как я, любите пользоваться git commit -a ).Даже изменение описания коммита приводит к необходимости его перезаписи, ведь хэш считается и от описания тоже!

Но это тривиальный случай. Давайте рассмотрим более интересные.

Допустим, вы сделали большие результаты, которые пилили несколько дней, отсылали ежедневно работы в репозиторий на сервере (4-5 коммитов), и отправили свои изменения на ревью. Двое-трое неутомимых ревьюверов закидали вас крупными и мелкими рекомендациями правок, а то и вовсе нашли косяки (ещё 4-5 коммитов).Затем QA нашли несколько краевых случаев, тоже требующих исправлений (ещё 2-3 коммита). И наконец при инженерии пробнились какие-то несовместимости или попадали автотесты, которые тоже надо пофиксить.

Если теперь нажать, не глядя, кнопку Merge, на главную ветку (у многих она по старинке называется master) вольются полтора десятка коммитов типа «Моя функция, день 1», «День 2», «Исправить тесты», «Исправить обзор »и ​​т.д. От этого, конечно, помогает режим сквоша, который сейчас есть и в GitHub, и в GitLab, но с ним надо быть осторожными: во-первых, он может заменить описание коммита на что-то непредсказуемое, а во-втором — заменить автора фичи на того, кто нажал кнопку Merge (у нас это вообще робот, помогающий релиз-инженеру собрать сегодняшний деплой).Поэтому самым главным будет перед окончательной интеграцией в релиз схлопнуть все коммиты ветки в одном при помощи git rebase .

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

У меня рука машинально потянулась к кнопке «Сообщить о нарушении», потому что как ещё можно охарактеризовать реквест из 50 коммитов с почти 2000 измененными строк? И как его, спрашивается, ревьюить?

Честно говоря, у меня ушло два дня просто на то, чтобы заставить себя приступить к этому ревью.И это нормальная реакция для инженера; кто-то в подобной ситуации, просто не глядя, жмёт Одобряю, понимая, что за разумное время всё равно не соответствует работе по обзору этого изменения с достаточным качеством.

Но есть способ облегчить жизнь товарищу. Помимо предварительной работы по лучшей декомпозиции, уже после завершения написания основного кода можно привести его историю написания в более логичный вид, разбив на атомарные коммиты с зелёными тестами в каждом: «создал новый сервис и транспортный уровень для него», «построил модели и написал. Проверка инвариантов »,« добавил валидацию и обработку исключений »,« написал тесты ».
Каждый из таких коммитов можно ревьюить по отдельной (и GitHub, и GitLab это умеют) и делать это набегами в моменты переключения между своими задачами или в перерывах.

Сделать это всё нам поможет всё тот ​​же git rebase с ключом --interactive . В качестве программы надо передать ему хэш коммита, начиная с которого нужно переписать историю. Если речь идет о последних 50 коммитах, как в примере на картинке, можно написать git rebase --interactive HEAD ~ 50 (подставьте вместо «50» вашу цифру).

Кстати, если вы в процессе работы над подливали к себе ветку мастер, то сначала надо будет сделать перебаз на эту ветку, чтобы объединить-коммиты и коммиты из мастера не путались у вас под ногами.

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

Иллюстрации взяты из книги Pro Git

Если изменения в C4 и C3 конфликтуют, то после второго разрешения конфликтов коммит C4 изменил свое содержание, поэтому он переименован на схему в C4 ’.

Таким образом, вы получите ветку, состоящую только из ваших изменений, и растущую из вершины master. Само собой, мастер должен быть актуальным. Можно просто использовать версию с сервера: git pull --rebase origin / master (как известно, git pull равносилен git fetch && git merge , а ключ --rebase заставит git сделать rebase вместо merge).

Вернёмся наконец к git rebase --interactive . Его делали программисты для программистов, и понимая, какой стресс люди будут испытывать в процессе, постарались максимально нервы сохранить пользователя и избавить его от чрезмерно напрягаться.Вот что вы на экране:

Это репозиторий популярного пакета Guzzle. Похоже, что перебазировать ему не помешал бы…

В текстовом редакторе открывается сформированный файл. Внизу вас ожидает подробная справка о том, что тут вообще делать. Далее в режиме простого редактирования вы решаете, что делать с коммитами в вашей ветке. Всё просто, как палка: pick — оставить как есть, reword — поменять описание коммита, squash — слить воедино с предыдущим (процесс работает снизу вверх, то есть предыдущий — это который строчкой ниже), drop — вообще удалить, отредактировать — и это самое интересное — остановиться и замереть.После того, как git встретит команду edit, он встанет в позицию, когда изменения в коммите уже добавлены в режим постановки. Вы можете поменять всё, что угодно в этом коммите, добавить его ещё несколько, и после этого скомандовать git rebase --continue , чтобы продолжить процесс rebase.

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

Если вы запутались и кажется, что всё пропало, у вас есть кнопка аварийного катапультирования git rebase --abort , которая немедленно вернёт всё как было.

. Хорошим тоном, как я уже написал выше, что тесты в каждом коммите будут зелёными (для этого отлично помогает редактировать и на следующем проходе — сквош).

Ещё одна фигура высшего пилотажа, полезная в случае, если надо несколько изменений в одном и том же файле разложить по разным коммитам — git add --patch . Она полезна и сама по себе, но в сочетании с директивой edit она позволит вам разделить один коммит на нескольких строках, что не позволяет, если я не ошибаюсь, ни один GUI-клиент и ни одна IDE.

Убедившись ещё раз, что всё в порядке, вы наконец можете со спокойной душой сделать то, с чего начался этот туториал: git push --force .Ой, то есть, разумеется, - force-with-lease !

Палу вы, скорее всего, будете тратить на этот процесс (включая первоначальный rebase на master) час, а то и два, если фича реально развесистая. Но даже это намного лучше, чем ждать два дня, когда ревьювер заставит себя наконец взяться за ваш реквест, и еще пару дней, пока он сквозь него продерётся. В будущем же вы, скорее всего, будете укладываться в 30-40 минут. Особенно помогает в этом продукте линейки IntelliJ со встроенным инструментом разрешения (полное раскрытие: компания FunCorp оплачивает эти продукты своим сотрудникам).

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

Спасибо за внимание всем, кто дочитал до конца! Надеюсь, что статья будет полезна не только вам, но и коллегам, ваш код попадает на ревью. Если у вас есть клёвые хаки для git — делитесь ими в комментариях!

.

Что именно делает «u»? «git push-U origin master» против «git push origin master»

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

от kernel.org для git push :

— u

— установка восходящего потока

для каждой ветви, которая обновлена ​​или успешно нажата, добавлена ​​ссылка вверх по течению (отслеживание), используется без аргументов git-pull (1) и другими командами. Дополнительные сведения см.В разделе ветка . <Имя> .merge в git-config (1).

здесь ветка. <Имя> .merge С git config :

филиал. <Имя> .merge

определяет совместно с ветвь. <Имя> .remote , восходящая ветвь для данной ветви. Он сообщает git fetch / git pull, какую ветвь объединить, а также может повлиять на git push (см. Push.неисполнение.) Когда в ветви , он сообщает git fetch, что refspec по умолчанию будет отмечен для слияния в FETCH_HEAD.Значение обрабатывается как удаленная часть refspec и должна соответствовать ref, который извлекается из удаленного, заданного "ветка. <Имя> .remote" . Эти сведения о слиянии используются git pull (который сначала git fetch) для поиска по умолчанию для слияния. Без этой опции git pull по умолчанию сливает первый извлеченный refspec. Укажите несколько значений, чтобы получить слияние осьминогов. Если вы хотите настроить git pull так, чтобы он сливался в <имя> из другой ветки в локальном репозитории, вы можете указать ветку .<имя> .merge в нужную ветку, и используйте специальную настройку. (точка) для ветки . <имя> .remote .

я успешно настроил удаленный репозиторий с github, и я успешно нажал свою первую фиксацию на него с помощью:

  git push -u origin master
  

я невольно нажал свою вторую фиксацию в удаленном репозитории, используя:

  git commit -m '[...]'
  

однако, неправильно думая, что мне придется снова нажать на origin С master , я побежал:

  # примечание: no -u
git push origin master
  

что же делать? Казалось, это не произвело никакого эффекта.Разве я «отменял» git push -u origin master ?

222

автор: ClosureCowboy

ключ «аргумент-менее git-pull». Когда вы делаете git pull из ветви, без указания источника удаленного или ветви, git смотрит на ветку .<имя> .merge настройка, чтобы знать, откуда тянуть. git push -u устанавливает эту информацию для ветви, которую вы нажимаете.

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

  $ git checkout -b тест
  

во-первых, мы нажимаем без -u :

  $ git push origin test
$ git pull
Ты попросил меня потянуть, не сказав, какую ветку ты
хотите объединить, и "branch.test.merge" в
ваш файл конфигурации тоже не сообщает мне об этом.пожалуйста
укажите, какую ветку вы хотите использовать в командной строке и
попробуйте еще раз (например, 'git pull  ').
Подробнее см. Git-pull (1).

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

    [ветка "тест"]
    remote = <ник>
    merge = 

    [удаленный "<ник>"]
    url = 
    fetch = 

Подробнее см. Git-config (1).
  

теперь, если мы добавляем -u :

  $ git push -u origin test
Настройка теста ветвления для отслеживания удаленного теста ветвления из источника.Все актуально
$ git pull
Уже актуально.
  

обратите внимание, что отслеживание информации была настроена так, что git pull работает, как ожидалось, без указания удаленного или ветви.

обновление: чаевые:

  • как Марк упоминает в комментариях, в дополнение к git pull этот параметр также влияет на поведение по умолчанию git push . Если вы привыкли использовать -u , чтобы захватить удаленную ветку, вы собираетесь установить ваш push.по умолчанию значение config для восходящего потока .
  • git push -u HEAD будет толкать текущую ветвь с тем же именем на (а также можно было отслеживать настройку, чтобы вы могли сделать git push после этого).
  git push -u origin master
  

— это то же, что:

  git push origin master; git branch --set-upstream master origin / master
  

сделать последнее заявление, если вы забыли -u !

или вы могли бы заставить его:

  git config branch.master.remote origin
git config branch.master.merge ссылки / головы / мастер
  

, если вы хотите, чтобы вы сделали ваши ошибки, если вы не набрали несуществующую ветку, или вы не git remote add , хотя это может быть то, что вы хотите :).

в более простых терминах:

технически -u флаг ссылку на вышестоящий сервер, на который вы нажимаете.

важно то, что это позволяет вам сделать git pull без предоставления аргументов. Например, как только вы сделаете git push -u origin master можно назвать git pull и git будет знать, что вы на самом деле имели в виду git pull origin master .

|

4

автор: Adepoju Oluwasegun

все необходимые команды git bash, чтобы толкать и тянуть в Github:

  git статус
git pull
git add filefullpath

git commit -m "комментарии для файла отметки"
git push origin ветка / мастер
git удаленный -v
git журнал -2
  

Если вы хотите отредактировать файл тут:

  редактировать имя файла.*
  

чтобы увидеть все ветви и их коммиты:

  git шоу-ветка
  

-7

автор: Камта Мишра

.

Что такое «git remote add …» и «git push origin master»?

Обновление : обратите внимание, что принятый в настоящее время ответ увековечивает распространенное заблуждение о поведении git push , который не был исправлен, несмотря на комментарий, указывающий на это.

резюме того, что пульты вашего дистанционного управления-как псевдоним для URL-адреса репозитория-правильно.

так почему же URL не git: //[email protected]/peter/first_app.git но в другом синтаксисе — что это за синтаксис? Почему это должно закончиться? с.ГИТ? Я старался не использовать .git в конце, и это тоже работает. Если нет .ГИТ, что еще это может быть? Git у новичка, похоже, является учетной записью пользователя на сервере git?

URL-адреса, которые вы указали, указали, что указали два разных транспортных протокола. Тот, который начинается с git: // для протокола git, который обычно используется только для доступа только для чтения к репозиториям.Другой, [email protected]: peter / first_app.git , является одним из различных способов указания доступа к репозиторию SSH-это «синтаксис стиля scp», в документация. Что имя пользователя в синтаксисе стиля scp является git из — за того, как GitHub имеет дело с идентификацией пользователей-по существу, это имя пользователя игнорируется, и пользователь идентифицируется на основе пары ключей SSH, которую они использовали для аутентификации.

что касается многословия git push origin master , вы заметили, что после первого толчка, вы можете просто сделать git push .Это из-за серия трудных для запоминания, но в целом полезных значений по умолчанию 🙂

  • , если удаленный не указан, удаленный настроен для текущей ветви (в remote.master.url в вашем случае) используется. Если это не настроено, то это.
  • если нет «refspec» (например, master , master: my-эксперимент и т. Д.) Указано, затем git по умолчанию нажимает каждую локальную ветвь, которая имеет то же имя, что и ветвь на удаленном компьютере.Если у вас просто есть ветка под названием master между общим и удаленным вашим репозиторием master на пульт master .

лично, так как у меня, как правило, часто несколько пультов, я всегда использую формулу:

  мастер git push origin
  

… чтобы случайно не толкать другие ветки.


в ответ на ваши комментарии по одному из других ответов, как будто — это изучается сверху вниз очень эффективно — вы представляете, что значения по умолчанию работают, и ваш вопрос спрашивает, Почему;), чтобы быть более серьезным, git может , но это действительно может изменить способ работы к лучшему, как SVN, но зная немного о пультах и ​​ветвях.Скотт Чакон в интервью подкаста-студентов учат всем основным инструментам в информатике и разработке программного обеспечения, но очень редко контроль версий. Распределенные системы управления версиями, такие как git и Mercurial, теперь настолько важны и настолько гибки, что стоило бы преподавать курсы по ним, чтобы дать людям хорошее обоснование.

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

  • первичная документация для git так трудно разобрать для новичков. (Хотя я бы сказал, что если Google для почти любого вопроса git, полезный учебный материал (или ответы переполнения стека :)) появляются в настоящее время.)
  • в git есть несколько странных поведений.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *