Советы по организации работы c Git / Хабр
Как обычно используют git? Пара базовых команд, чтобы «всех синхронизировать». Разочарование от git часто возникает у тех, кто никогда не выходит за пределы этого поверхностного понимания. Однако освоение git наверняка окупится. Сколько времени вы тратите на использование git? Я бы предположил, что на вашем поясе немало инструментов, которые вы используете вдвое реже и потратили вдвое больше времени на изучение.
Если хотите больше узнать о git, предлагаю начать с главы 10 книги Pro Git (это бесплатно!), затем главы 2, 3 и 7. Остальное необязательно. В этой статье мы обсудим, как применить описанные в книге инструменты для дисциплинированной и продуктивной работы в git.
Возможно, вы слышали это раньше, но потерпи́те. Как правило, не нужно использовать git commit -m "ваше сообщение здесь"
. Начните с настройки git для использования любимого редактора: git config --global core.editor vim
, затем просто запустите git commit
Мы используем 72 символа, потому что это стандартная ширина сообщения электронной почты, а электронная почта — важный инструмент для git. Ограничение в 50 символов используется, потому что первая строка становится темой вашей электронной почты, и в начало можно добавить много текста вроде
. Вы можете найти такие ограничения форматирования раздражающими и обременительными, но учтите, что другие читают логи не в том же контексте, что и вы. Я часто читаю логи коммитов на вертикальном мониторе, и он не втиснет в одну строку столько текста, сколько ваш дисплей 4K 16:9.
Каждый коммит должен содержать только одно изменение — избегайте небольших несвязанных изменений в одном коммите (в этом отношении я мог бы почаще прислушиваться к собственным советам). Кроме того, избегайте разбиения одного изменения на несколько коммитов, если только идея не разбивается на отдельные шаги, каждый из которых представляет собой полноценное изменение. Если в вашем рабочем дереве несколько изменений и вам нужно зафиксировать только некоторые из них, попробуйте
git add -i
или git add -p
. Кроме того, каждый коммит должен компилироваться, успешно проходить все тесты и избегать известных багов, которые будут исправлены в будущих коммитах.Теперь можно взять любой коммит и ожидать, что код будет работать правильно. Это пригодится и позже, например, в процессе выборочного включения коммитов в ветку релиза. Такой подход также повышает полезность git-bisect1, потому что если вы ожидаете, что код скомпилируется и успешно пройдёт тесты для каждого коммита, то вы можете передать
скрипт, который программно проверяет дерево на наличие ошибки и избежит ложных срабатываний. Эти автономные коммиты с хорошими описаниями упростят подготовку описаний релиза с помощью git-shortlog, как это делает Линус с релизами Linux.
Мы подходим к одной из самых важных особенностей git, которая отличает его от своих предшественников: редактирование истории. Все системы управления версиями поставляются с какой-то «машиной времени», но раньше они были в основном доступны только для чтения. Однако машина времени git отличается: вы можете изменить прошлое. На самом деле вас даже поощряют делать это! Но предупреждаю: изменяйте только то прошлое, которое ещё не вошло в стабильную публичную ветку.
git commit -m fixup
), а затем использую git rebase -i
, чтобы влить его в более ранний коммит.- Читайте маны! Выберите случайную страницу git man и прочитайте её сейчас. Кроме того, если вы не читали страницу git man верхнего уровня (просто
), сделайте это.
- В нижней части каждого мана для команды git высокого уровня обычно находится список команд git низкого уровня, на которые опирается команда высокого уровня. Если хотите узнать больше о том, как работает команда git высокого уровня, попробуйте прочитать эти справочные страницы.
- Узнайте, как выбирать нужные коммиты с помощью rev selection.
- Ветки полезны, но вы должны научиться работать без них, а также иметь хороший набор инструментов на поясе. Используйте команды вроде
git pull --rebase
,git send-email -1 HEAD~2
и
. git push origin HEAD~2:master
1. В двух словах, git bisect — это инструмент, который выполняет двоичный поиск между двумя коммитами в вашей истории, просматривая коммиты между ними по одному, чтобы вы могли проверить наличие ошибки. Таким образом можно вычислить коммит, который вызвал проблему. ↑
Зачем нужен Git – Hexlet Guides
Содержание
- Какие задачи решает контроль версий
- Как работает контроль версий
- Какие бывают системы контроля версий
- Первое поколение
- Второе поколение
- Третье поколение
- Заключение
В этом руководстве пойдёт речь об основах Git. Вы узнаете, зачем нужен контроль версий, как работают системы контроля версий. В дальнейшем информация позволит успешно освоить практическую работу с Git.
Какие задачи решает контроль версий
Независимо от выбранного языка или направления разработки, код, который пишет программист, остаётся обычным текстом, записанным в множестве файлов на диске. Эти файлы регулярно добавляются, удаляются и изменяются. Некоторые из них могут содержать сотни строчек кода, а другие тысячи. Файлы в тысячу строк кода — вполне нормальное явление в программировании.
Пока проект состоит из пары-тройки файлов, его разработка не создаёт никаких сложностей. Программист пишет код, запускает его и радуется жизни. Клиент доволен, заказчик тоже. С ростом кодовой базы появляются определённые неудобства, которые затем превращаются в реальные проблемы:
- Как не потерять файлы с исходным кодом?
- Как защититься от случайных исправлений и удалений?
- Как отменить изменения, если они оказались некорректными?
- Как одновременно поддерживать рабочую версию и разработку новой?
Представьте, что ваш проект состоит из сотни файлов и десятков тысяч строк кода. Вы делаете какую-то задачу, в процессе меняете 15 файлов и 300 строк кода и вдруг становится понятно, что эта задача больше не актуальна. На этом моменте нужно вернуться к состоянию исходного кода, которое было до изменений. И это только один из множества вариантов событий. Другой вариант — в процессе работы над кодом стало понятно, что нужно срочно внести исправление в рабочий проект (сайт). Новую задачу в нерабочем состоянии выкладывать на сайт нельзя, а это значит, что исправление нужно вносить в ту версию кода, которая была до начала реализации новой задачи.
Самый простой вариант решения, указанных выше проблем — копирование директорий. К сожалению, такой подход обладает только недостатками. Перенос изменений из одной директории в другую возможен только полной перезаписью, так как точечные изменения отследить невозможно (только по памяти). Как только папок станет две, вы сразу начнёте путаться в них. И всё равно этот способ никак не поможет работать над кодом одновременно двум людям.
Совместная разработка — это отдельная головная боль. Если два программиста работают над задачами, требующими исправления кода в одних и тех же файлах, то как они выполнят эту работу так, чтобы не повредить или перезаписать изменения другого разработчика?
К счастью, эту задачу решили ещё в 80-х годах. С тех пор инструментарий сильно развился и стал использоваться повсеместно не только для кода, но и, например, для написания и перевода книг. Решением является контроль версий. Выполняется он с помощью специальных программ, которые умеют отслеживать изменения кода. Вот некоторые из многочисленных возможностей данных систем:
Возврат к любой версии кода из прошлого.- Просмотр истории изменений.
- Совместная работа без боязни потерять данные или затереть чужую работу.
В этом руководстве мы разберём общие принципы работы подобных программ.
Как работает контроль версий
Системы контроля версий (СКВ или VCS — Version Control System) часто встроены в инструменты, привычные даже далёким от программирования людям. Именно с них мы и начнём своё знакомство, а заодно погрузимся в соответствующую терминологию.
Сервисы синхронизации файлов между устройствами, такие как Dropbox, используются практически всеми. И все они отслеживают версии файлов, с которыми работают. Происходит это так: периодически программа синхронизирует локальные файлы с теми, которые находятся в хранилище сервиса. Если локальный файл отличается, и время его изменения – позже файла, находящегося на сервере, то файл на сервере становится частью истории изменений, а текущим становится последний изменённый файл.
На картинке выше текущая версия файла обозначена как current. Всё остальное – это предыдущие версии текущего файла. Как видно, Dropbox позволяет восстановить любую версию файла.
Обратите внимание на эту фразу:
Dropbox keeps a snapshot every time you save a file. (Дропбокс сохраняет снимок каждый раз, когда вы сохраняете файл)
Снимок (snapshot; разг. снепшот) – очень важное понятие, которое будет встречаться нам в будущем. Его ещё называют снимком состояния или даже мгновенным снимком (буквальный перевод), но для простоты будем называть его просто «снимок».
В данном случае, снимок – это сам файл после изменения. И чтобы лучше понять этот термин, посмотрим на альтернативу — дельту изменения (diff). Представьте, что вместо сохранения новой версии файла Dropbox бы вычислял разницу между новым и старым файлом (а это не сложно сделать для текстовых файлов) и сохранял только её. Зачем так делать, спросите вы? Такой подход позволяет сэкономить место на диске, хотя и вносит дополнительную сложность при работе с файлами.
В дальнейшем мы увидим, что разные инструменты используют разные подходы: некоторые работают с дельтой изменений, другие — со снимками. Кстати, термин «снимок» часто применяют к дискам. Например, можно сделать снимок диска и потом восстанавливаться с этой точки (прямо как в играх).
Другим хорошим примером использования контроля версий являются текстовые редакторы, в первую очередь онлайновые.
Сервис Google Docs автоматически делает снимки после каждого автосохранения (примерно раз в 5 секунд). Если документ за это время не изменился, то, естественно, новая версия не появляется. Множество таких версий образуют историю изменений.
На картинке выше история версий называется “Revision history”. Ревизия — базовое понятие систем контроля версий. Любое зафиксированное изменение в системе контроля версий называется ревизией.
Обратите внимание на то, что ревизия и снимок – это не одно и то же. Фиксация изменений создаёт ревизию, но сама ревизия может содержать внутри себя либо де
Как научить людей использовать Git / Хабр
По работе приходится участвовать в разных проектах, поэтому я хорошо знаю, как работают все мои коллеги. Помню, что компания начала использовать Git буквально за пару недель до моего прихода. На мониторах разработчиков кругом висели наклейки с напоминанием: сначала add, потом коммит, затем пуш.Они не знали, зачем. Программистам просто сказали строго следовать инструкции, иначе беда. Но проблемы возникали так часто, что я решила провести семинар по Git.
Мне нравится составлять карту в голове. Я не говорю «ментальные карты», потому что это хорошо известный тип диаграмм. Речь о неких картинках, структурах или любом графическом представлении в уме. Например, в детстве я учила арифметику, представляя игральные кубики.
Поэтому я подготовила несколько рисунков. Не обязательно их смотреть, чтобы понять текст. Для каждого есть пояснение.
Кроме того, очень важно научить человека терминам. Иначе он не поймёт сообщения от Git. Рисунки — хороший способ.
На рисунке четыре области распределены следующим образом:
- Среда разработки:
- Рабочий каталог
- Промежуточная область (staging) или индекс
- Локальный репозиторий
- Сервер:
- Удалённый репозиторий
Здесь можно объяснить преимущества распределённой системы управления версиями.
При клонировании данные из удалённого репозитория перемещаются в две области:
- Рабочий каталог
- Локальный репозиторий
В рабочем каталоге два типа файлов:
- Отслеживаемые: файлы, о которых знает Git.
- Неотслеживаемые: которые ещё не были добавлены, поэтому Git не знает о них.
После подготовки изменений в рабочем каталоге их необходимо добавить в промежуточную область (staging area).
Когда там накопился ряд изменений с общей целью, самое время создать в локальном репозитории коммит с сообщением об этой цели.
Если в локальном репозитории есть один или несколько коммитов, готовых к совместному использованию всем остальным миром, они отправляются в удалённый репозиторий.
В этот момент можно говорить о различных состояниях файла в среде разработки: изменённом, промежуточном (staged) и зафиксированном (commited).
Далее вы можете объяснить:
- как показать изменения файла в рабочем каталоге:
git diff
- как показать изменения файла в промежуточной области:
git diff --staged
- как изменить файл в рабочем каталоге после добавления в промежуточную область
- и т. д.
Получение (fetching)
При выполнении git fetch
данные из удалённого репозитория перемещаются только в локальный репозиторий.
Вытягивание (pulling)
При выполнении git pull
данные из удалённого репозитория перемещаются в две области:
- В локальный репозиторий:
fetch
- В рабочий каталог:
merge
Если важна история коммитов, рассмотрите возможность использования
git pull --rebase
. Тогда вместо команд fetch + merge
выполняются команды fetch + rebase
. Ваши локальные коммиты будут воспроизведены, так что вы не увидите в истории коммитов известную форму бриллианта.Можете добавить в среду разработки ещё одну область, чтобы проще прятать накопленные изменения: грязный рабочий каталог.
Когда люди усвоят эти понятия, вам будет легче объяснить дальнейшее: ветви, историю коммитов, перебазировку и так далее, потому что прочный фундамент уже заложен.
Я работала с другими системами управления версиями (Visual SourceSafe, TFS и Subversion): по моему скромному опыту, недостаток знаний вредит и со старым инструментом, и с новым. Сосредоточьтесь не только на выборе инструмента, но и на его освоении.
Мой друг Марк Виллаграса напомнил, что очень полезно решить задачки Git и делиться с коллегами решением.
Ресурсы из комментариев на Hacker News:
Прочитав комментарии на Reddit, я подумала, что более точным названием этой статьи было бы «Идея, как научить людей использовать Git», потому что это только идея, которая появилась в моей голове, когда я сама несколько лет назад изучала Git по книге Pro Git. Статья не является полным руководством, лишь отправная точка. Уверена, что все эти ресурсы будут очень полезны. Спасибо!
И спасибо Стюарту Максвеллу, который поделился ссылкой на Hacker News, и u/cryptoz, который запостил её на Reddit!
Знакомство с работой Git – и не только с командами
Git, заметки для самого себя
Андре Фашат
Опубликовано 01.09.2015
Git — это популярный децентрализованный репозиторий исходного кода. Его разработал Линус Торвальдс, создатель операционной системы Linux, для управления исходным кодом ядра Linux. На нем основаны целые службы, такие как GitHub. Он используется даже в IBM DevOps Services – наряду с IBM Rational Team Concert™. Так что тем, кто хочет программировать в мире Linux или использовать IBM DevOps Services с Git, будет полезно хорошее понимание Git.
Когда я начал работать с Git, я имел некоторый опыт работы с Concurrent Versions System (CVS) и Apache Subversion (SVN), поэтому я пытался освоить его с точки зрения этих классических систем хранения исходного кода. Такой подход дал мне лишь ограниченное понимание возможностей Git. С тех пор я освоил Git гораздо лучше, так что эта статья – своего рода «Заметки для самого себя», чтобы напомнить себе, как работает Git, и объяснить это всем начинающим. Я предполагаю, что вы знакомы с другими, более классическими хранилищами исходного кода, такими как CVS или SVN.
Основы
Так что давайте начнем с простого примера классического репозитория исходного кода, показанного на рисунке 1. В классическом репозитории исходного кода папка с файлами и подпапки обрабатываются как информация (content) (CVS и Git на самом деле работают не с папками, а просто с файлами по указанному пути). Все версии информации содержатся в репозитории, а рабочий каталог – это место, где работают с кодом. Из репозитория код выгружают (checkout) в рабочий каталог, а изменения, внесенные в этом рабочем каталоге, фиксируют (commit) в новой версии информации в репозитории.
Рисунок 1. Управление рабочим пространством в классическом репозитории исходного кода
При каждой операции фиксации создается новая версия информации, полученная из предыдущей, родительской версии в результате внесения изменений, как показано на рисунке 2. Информация хранится в виде ряда версий, также называемых снимками текущего состояния (snapshots), которые связаны отношениями «родитель-потомки» в результате операций фиксации. Информация, измененная между родительской и дочерней версиями путем фиксации, называется набором изменений.
Такая последовательность версий называется потоком или ветвью. В SVN основной поток называется стволом; в CVS он обычно носит имя HEAD; в Git его обычно называют master. Ветви используются при реализации проекта для выделения разработки конкретной функции или для поддержки старой версии.
Рисунок 2. Создание новой версии в классическом репозитории
Пока Git мало чем отличается от классических хранилищ исходного кода, не правда ли? К сожалению, на этом сходство заканчивается. Одна из основных особенностей CVS и SVN заключается в том, что у них есть центральный репозиторий. Git – децентрализованный репозиторий. При разработке программного обеспечения несколько репозиториев могут работать одновременно, и они так и работают, потому что репозиторий каждого разработчика действует и сообщается с другими точно так же, как любой другой Git-репозиторий на сервере.
Так как же работает Git?
Основной принцип работы Git на удивление прост – его только нужно усвоить.
Во-первых, Git манипулирует информацией в форме снимков текущего состояния, по одному на каждую фиксацию, или «коммит», и «знает», как применить набор изменений для перехода к следующему состоянию или возврата к предыдущему. Это важная концепция. По-моему, понимание идеи применения набора изменений и отката значительно упрощает освоение Git.
Это поистине основополагающий принцип. Все остальное – его следствия. Так что давайте немного углубимся в Git.
Работа с Git
Чтобы начать работу с Git, достаточно выполнить команду git init
. Она превращает текущий каталог в рабочий каталог Git и создает в нем подкаталог .git
(скрытый) с репозиторием. Теперь можно приступать к работе с Git. Команды checkout
и commit
такие же, как и в других репозиториях исходного кода, но акцент делается на наборы изменений, поэтому в Git есть команда add
(как в SVN). С помощью этой команды изменение, внесенное в рабочий каталог, переносится в промежуточную область для следующей фиксации. Эту промежуточную область обычно называют индексом. Рисунок 3 иллюстрирует процесс создания набора изменений из снимка версии A в снимок версии B.
Команда git status
помогает отслеживать добавленные изменения, в какой бы ветви вы ни находились.
Рисунок 3. Создание набора изменений в Git
Команда git log
показывает историю изменений (т.е. коммитов) в рабочем каталоге, а команда git log <path>
– историю изменений по данному пути.
Команда git status
перечисляет измененные файлы в рабочей области, а также файлы в индексе, а с помощью команды git diff
можно увидеть различия между файлами. Используя только команду git diff
(без параметров), можно увидеть изменения в рабочем каталоге, которые еще не добавлены в индекс. Чтобы увидеть, что на самом деле находится в индексе, – то есть изменения, ожидающие своей очереди, нужно использовать команду git diff --cached
. Команда git diff <name>
или git diff <name> -- <path>
показывает разницу между текущим рабочим каталогом и указанным коммитом в рабочем каталоге или по данному пути соответственно. Name может быть идентификатором фиксации, именем ветви или другим именем. Теперь самое время поговорить об именах.
Имена
Примечание.
Из-за длинных идентификаторов коммитов я буду использовать на своих рисунках только аббревиатуры, такие как «(A)», «(B)» и т.п.
Рассмотрим принципы именования объектов в Git. Основные элементы Git – это снимки текущего состояния. Их называют по идентификаторам коммитов, которые представляют собой идентификаторы хешей, например, «c69e0cc32f3c1c8f2730cade36a8f75dc8e3d480». Их получают из содержимого снимка, который включает в себя фактическую информацию и некоторые метаданные, такие как время подачи, сведения об авторе, родительская версия и т.д. Снимок не имеет номера версии через точку, как в CVS, и номера операции (и пути относительно каталога верхнего уровня /branches), как в SVN. Поэтому между именами снимков текущего состояния Git невозможно установить какой-либо порядок, как в других репозиториях. Для удобства Git позволяет сокращать эти длинные хэши до кратких имен с минимальным количеством символов от начала ID, так чтобы краткое имя все равно оставалось уникальным в пределах репозитория. В приведенном выше примере кратким именем будет «c69e0cc».
Отметим, что термин commit используется и как глагол, означающий действие по созданию снимка текущего состояния, и как имя существительное, означающее результирующий снимок.
Обычно с идентификаторами снимков не работают; работают с ветвями. В других репозиториях ветвью называют именованный поток изменений исходного кода. В Git поток изменений — это список наборов изменений, следующих в том порядке, в каком они применяются, один за другим, при движении от одного снимка текущего состояния к другому. Ветвь в Git – это всего лишь именованный указатель на определенный снимок. Он отмечает место, где должны применяться новые изменения при использовании данной ветви. Когда к ветви применено изменение, метка ветви также перемещается к новому коммиту.
Как Git «узнает», куда поместить изменения из рабочей области? На это указывает HEAD. HEAD разработки — это место, откуда взято последнее рабочее пространство и, что еще важнее, куда фиксируются изменения. Обычно HEAD указывает на ветвь последней выгрузки. Это отличается от интерпретации термина HEAD в CVS как вершины разработки ветви по умолчанию.
Команда tag
указывает коммит и позволяет адресовать отдельный коммит с читабельным именем. Как правило, тег (tag) — это псевдоним, заменяющий идентификатор коммита, но коммиты могут обозначаться и ярлыками. HEAD – это вершина разработки в рабочем каталоге. HEAD^1 — первый родитель коммита HEAD, HEAD^2 – второй и т.д.
Подробнее см. на странице руководства gitrevisions. Так как имена, такие как теги или имена ветвей, указывают на коммиты, они называются указателями (refnames). Команда reflog показывает, что изменилось за время жизни имени, с момента его создания (обычно вместе с ветвью) до текущего состояния.
Ветвление
Идея ветвления заключается в том, что каждый снимок текущего состояния может иметь более одного потомка. Применяя второе изменение к одному и тому же снимку, вы создаете новый, отдельный поток разработки. И если ему присвоено имя, то он называется ветвью.
Рисунок 4. Пример структуры ветвления в Git
Рисунок 4 иллюстрирует эту структуру ветвей в Git. Ветвь master, где в настоящее время происходит некоторая разработка, указывает на снимок F. Другая ветвь, old, соответствует более старому снимку, возможно, точке исправления разработки. Ветвь feature содержит другие изменения – для конкретной функции. Наборы изменений помечены как переходы из одной версии в другую, например, «[B->D]». В этом примере у снимка текущего состояния B есть два потомка, два направления развития, – ветвь feature и другая ветвь. Коммит А также помечен как исправление ошибки номер 123.
Ветви создаются посредством применения команды git branch <branch name>
к текущему HEAD или команды git branch <branch name> <commit id>
к любой допустимой версии снимка текущего состояния. Это приводит к созданию нового указателя ветви в репозитории. Будьте внимательны, при ветвлении таким способом рабочая область остается в старой ветви. Сначала нужно выгрузить новую ветвь. Команда git checkout -b <branch name>
создает новую ветвь и переносит в эту ветвь рабочую область.
Есть еще две чрезвычайно полезных команды:
git diff <branch> -- <path>
, как уже упоминалось, показывает различия для данного пути (файла или каталога) между текущим рабочим каталогом и указанной ветвью;git checkout <branch> -- <path>
извлекает файлы из другой ветви в рабочий каталог, так что можно взять изменения из другой ветви.
Слияние
При реализации новой функции ее загружают в репозиторий, например, в ветвь feature. Когда функция готова, необходимо вернуть ее в основную ветвь (master). Для этого нужно выгрузить основную ветвь и воспользоваться командой git merge <branch name>
. Тогда git объединит изменения из данной ветви с выгруженной ветвью. Для этого Git применяет все наборы изменений из ветви feature к вершине основной ветви.
Существует три способа достижения этой цели в зависимости от типа изменений в этих двух ветвях и возможных конфликтов.
- Быстрое прямое слияние: в принимающей ветви не произошло никаких изменений с тех пор, как две ветви разошлись. Она по-прежнему указывает на последний коммит, предшествующий отделению другой ветви. В этом случае Git перемещает указатель принимающей ветви вперед, как показано на рисунке 5. Так как кроме продвижения указателя ветви ничего делать не нужно, в Git это называется «быстрым прямым слиянием».
Рисунок 5. Быстрое прямое слияние
- Бесконфликтное слияние: имеются изменения в обеих ветвях, но они не конфликтуют. Это происходит, например, если изменения в обеих ветвях влияют на разные файлы. Git автоматически применяет к принимающей ветви все изменения из другой ветви и создает новый коммит с этими изменениями. Затем принимающая ветвь перемещается вперед к этому коммиту, как показано на рисунке 6.
Обратите внимание, что результирующий коммит – merge commit – имеет двух родителей. Однако я не отметил здесь наборы изменений. В принципе, набор между изменений (E) и (H) будет комбинацией всех наборов изменений из ветви feature с момента расхождения двух ветвей, но это, вероятно, заводит аналогию слишком далеко.
Рисунок 6. Бесконфликтное слияние
- Конфликтное слияние: имеются изменения в обеих ветвях, и они конфликтуют между собой. В этом случае конфликтующий результат останется в рабочем каталоге, чтобы пользователь мог исправить и зафиксировать его или же отменить слияние командой
git merge –abort
.
Один интересный момент, который следует отметить, заключается в том, что при слиянии выявляются случаи, когда к обеим ветвям применено одно и то же изменение. Обычно изменение в обеих ветвях приводит к конфликту, но у Git достаточно интеллекта, чтобы выявить эту ситуацию, и тогда можно выполнить быстрое прямое слияние.
Понятие отката и повторения набора изменений ведет еще дальше, к таким расширенным возможностям, как сдвиг (rebasing) и выборочное применение изменений (cherry picking).
Иногда, пока вы разрабатываете функцию, основная разработка также продвигается вперед, но вы пока не хотите объединять с ней свою функцию. В результате обе ветви быстро расходятся друг с другом. Однако можно применять набор изменений одной ветви к другой. Для этого Git предлагает функции сдвига и выборочного применения изменений.
Сдвиг
Представьте себе, что вы разрабатываете свою функцию, и вам нужно включать последние изменения из основной ветви, чтобы идти в ногу с генеральной линией разработки. Это называется сдвигом ветви вашей функции; точка расхождения между двумя ветвями перемещается вверх по одной из ветвей. В этом случае Git воспроизводит изменения из одной ветви в продолжении другой, создавая новые коммиты для каждого из первоначальных коммитов. В примере, показанном на рисунке 7, он пытается применить изменения из ветви feature к вершине ветви master.
Рисунок 7. Смещение ветви
Если повтор приводит к конфликту, смещение останавливается при первом же конфликте и оставляет конфликтующее состояние в рабочем каталоге для исправления пользователем. Затем смещение можно продолжить или прервать.
Смещение с параметром --onto
позволяет переместить точку расхождения смещения к любому новому снимку текущего состояния в другой ветви.
Выборочное применение изменений
Представьте себе, что, работая над функцией, вы придумали некоторое изменение, которое нужно немедленно ввести в основную ветвь разработки. Это может быть исправление ошибки или интересное решение, но вы пока не хотите объединять или смещать ветви. Git позволяет скопировать набор изменений из одной ветви в другую, используя функцию cherry pick.
В этой ситуации, как показано на рисунке 8, Git просто применяет набор изменений, ведущий к выбранному снимку текущего состояния, к состоянию HEAD, например, основной ветви. Для этого обычно используется идентификатор коммита, или значение хэша.
Рисунок 8. Выборочное применение изменений
Возврат
Команда revert
выполняет откат одного или нескольких наборов изменений в рабочий каталог, а затем создает новый коммит с результатом. revert
– это почти cherry pick наоборот. См. пример на рисунке 9.
Рисунок 9. Возврат коммита
Команда revert
документирует возврат как новый коммит. Если вы не хотите это документировать, можно сбросить указатель ветви до более раннего коммита, но это выходит за рамки настоящей статьи.
Почему я описываю все это так подробно? Потому что крайне важно понимать эти особенности, когда в следующем разделе мы будем говорить о возможностях сотрудничества. На самом деле тем, кто усвоил это первый раздел, во втором разделе почти сразу станет все ясно. Большая часть функций для совместной работы основана на базовой функциональности, описанной выше.
Сотрудничество
В классических хранилищах исходного кода всегда есть четкое указание на то, что это за ветвь; она находится в центральном репозитории.
В Git нет такого понятия, как основная ветвь. Подождите, но разве выше я не говорил, что обычно существует основная ветвь? Да, говорил. Однако эта основная ветвь существует только локально. Нет никакой связи между основной ветвью в одном репозитории и в другом, за исключением того отношения между ними, которые вы создадите.
Рисунок 10. Два репозитория
Если репозиторий уже есть, то с помощью команды git remote add
к нему можно добавлять удаленные репозитории. Затем в своем репозитории с помощью команды fetch
можно получить зеркальную ветвь удалённой ветви. Это называется ветвь дистанционного отслеживания, поскольку отслеживается разработка в удаленной системе.
При выгрузке ветви, которая существует только как ветвь дистанционного отслеживания (но не как локальная ветвь), Git автоматически создает локальную ветвь из ветви дистанционного отслеживания и выгружает ее.
После этого можно объединить содержимое удаленной ветви и своей собственной. На рисунке 11 показан процесс выгрузки удаленной ветви в локальную ветвь master, но это не обязательно, ее можно слить с любой другой ветвью с общей историей, например, с помощью обычной команды merge.
Рисунок 11. Извлечение и выгрузка удаленной ветви
Другой способ – команда git clone
, которая копирует удаленный репозиторий, например, из службы хостинга. Она автоматически получает все удаленные ветви (но еще не локальные ссылки) и выгружает основную ветвь.
Как видите, создается модель. Так как ветвь удаленного репозитория – это «просто ветвь», все, что говорилось выше о ветвлениях, слияниях и т.д., почти беспрепятственно применимо и здесь, особенно при получении изменений из удаленного репозитория.
Рисунок 12. Получение удаленных изменений
На рисунке 12 показано действие команды git fetch
; она обновляет ветвь дистанционного отслеживания. Затем просто выполняется обычная операция слияния между ветвью дистанционного отслеживания и локальной ветвью, в данном примере – git checkout master; git merge repo1/master
. После копирования имя FETCH_HEAD
можно использовать в команде слияния в качестве ярлыка скопированной удаленной ветви, например, git merge FETCH_HEAD
. Кроме того, как говорилось выше, это слияние может привести к быстрому прямому слиянию, бесконфликтному слиянию или к конфликту, который нужно разрешить вручную.
Команда git pull
удобна тем, что выполняет оба действия fetch
и merge
.
Когда изменения зафиксированы в локальной ветви, их нужно передать в удаленную ветвь. Это делается с помощью команды push
, которая переносит локальные изменения в удаленную ветвь. Это действие, противоположное действию fetch
, а не pull
. Однако это больше, чем просто копирование, так как обновляется как локальная копия удаленной ветви, так и удаленная ветвь в другом хранилище, как показано на рисунке 13. Команда push
также позволяет создавать новые ветви в удаленном репозитории.
Рисунок 13. Публикация изменения
Существует одно условие. Это срабатывает только в том случае, если операция push приведет к быстрому прямому слиянию с удаленной ветвью в удаленном репозитории. В противном случае в удаленной ветви уже есть другие изменения (коммиты) из других репозиториев или от других коммиттеров. Тогда Git прерывает операцию push и оставляет все как есть. Затем нужно извлечь изменения, объединить их со своей локальной ветвью и повторить попытку публикации.
Обратите внимание, что в таких случаях можно выполнить обычное слияние, а можно – слияние со смещением для переноса изменений из локальной ветви в новую, отредактированную вершину удаленной ветви.
Помимо команд fetch и push, есть еще один способ распространения изменений; старая добрая почта. Существует команда git format-patch <start-name>
, которая создаёт файл изменений для каждого коммита, ведущий от данного коммита к текущему состоянию ветви. Команда git am <mail files>
применяет эти файлы изменений к текущей ветви.
Предостережения
Одно предостережение: не пытайтесь выполнить операцию push в репозиторий, где кто-то уже отслеживает ветвь и локально работает с ней. Это скорее всего приведет к путанице в управлении ветвями – Git предупредит вас об этом и попросит сначала синхронизировать состояние удаленной ветви с помощью команды pull
.
Также понятно, что не следует смещать ветвь дистанционного отслеживания. Она перестанет совпадать с удаленной ветвью, и быстрого прямого слияния по команде push
не получится. Вы нарушили структуру репозитория.
Расширенный Git
Рисунок 14. Пример структуры с несколькими репозиториями
Обычно даже при использовании Git имеется структура в форме звезды с одним центральным репозиторием, который служит в качестве основного, и локальными репозиториями каждого пользователя. Но это не обязательно. Можно добавлять соединения с удаленными репозиториями с образованием паутины перекрестных соединений, например, как показано на рисунке 14.
Выше я описал сдвиг как воспроизведение наборов изменений поверх другой точки ветвления (или расхождения) исходной ветви. Как правило, Git воспроизводит порядок, в котором создавались коммиты. Расширенная функция git rebase -i
позволяет выбирать, в каком порядке должны следовать коммиты, и даже можно ли удалять коммиты или объединять два коммита друг с другом (squash). Этого нельзя делать с коммитами, которые уже опубликованы – иначе те, кто работает с ними, получат много конфликтов.
Я также описал, как выгрузить конкретную ветвь, но выгрузить можно любой коммит (снимок текущего состояния). Тогда указатель HEAD будет указывать на коммит, а не на ветвь. Этот режим называется detached HEAD. При фиксации изменения в этой ситуации начинается новый поток разработки. Как правило, вы совершаете ветвление, но без необходимости присваивать имя этой новой ветви. Вершина разработки доступна только через идентификатор коммита; у нее нет никакого имени refname. Можно создать ветвь от этой вершины с помощью обычной команды git branch <branchname>
.
Что происходит с теми коммитами, которые недоступны ни по какой ссылке? Если не делать ничего специально, то они останутся в репозитории. Однако можно – и службы хостинга так и делают – запустить git gc
, сборщик мусора Git для удаления ненужных файлов. Коммиты, не доступные ни по какому имени, не нужны и будут удалены. Поэтому рекомендуется всегда работать с реальной ветвью, особенно с учетом того, как быстро и легко создаются новые ветви в Git.
Заключение
С одной стороны, Git основан на простых принципах, но при этом он обеспечивает ошеломительную гибкость. Основное положение: Git управляет снимками текущего состояния и наборами изменений между ними. Наиболее распространенные команды применяют и отменяют эти наборы изменений между различными ветвями. Второе положение: управление удаленными ветвями в основном осуществляется так же, как и локальными, потому что есть локальное зеркало удаленной ветви.
На этом я заканчиваю свой краткий обзор работы с Git. Описанные команды в основном охватывают все, что я делаю с помощью Git. Более подробную информацию обо всех командах можно найти на соответствующих справочных страницах, а знания, полученные здесь, помогут вам лучше понять и использовать их. К тому же ценные указания на то, что делать дальше, часто дают сами команды и git status
.
Еще один отличный инструмент, помогающий понять Git, – это графический инструмент gitk, который показывает структуру локального репозитория. Используйте команду gitk --all
, чтобы увидеть все ветви, теги и т.п. Он также предоставляет простой интерфейс для выполнения действий в Git.
Обычно на Linux-системе Git уже установлен. Возможно, вам придется установить инструменты разработки из своего диспетчера пакетов. Для Windows его можно загрузить с главной страницы Git.
Я надеюсь, что теперь вы лучше понимаете, как работает Git, и не боитесь использовать его гибкость.
Спасибо за интересные дискуссии на эту тему и за рецензию на эту статью моему коллеге Витольду Щепонику, который знает Git еще лучше, чем я.
Ресурсы для скачивания
Похожие темы
Работа с Git через консоль — Блог HTML Academy
Итак, вы получили задание: сделать форк вашего репозитория в GitHub, создать ветку и начать работу.
Когда получил непонятное задание.Что за GitHub, какие команды, зачем, а главное, как всем этим пользоваться? Давайте разбираться.
Система контроля версий Git
Для начала определим, что такое система контроля версий.
Так называют программу, которая позволяет хранить разные версии одного и того же документа, легко переключаться между ранними и поздними вариантами, вносить и отслеживать изменения.
Систем контроля версий много и все они работают по принципу компьютерной игры, где вы можете вернуться к месту сохранения, если что-то пошло не так.
Одна из самых популярных систем называется Git. Её отличие от других программ — отсутствие графической версии. Поэтому работа с Git ведётся через командную строку. В разных операционных системах свои программы для взаимодействия с Git.
В Windows их две: PowerShell и cmd.exe. В Ubuntu это Terminal. Самая популярная программа на macOS тоже называется Terminal. Если вам не подходит встроенная в систему программа для работы с командной строкой, вы можете поставить свою. Например, написанную на JavaScript программу Hyper, которая работает на любой операционной системе. На Windows популярны программы Cmder и Git Bash, а на macOS — iTerm.
В мире разработки такие программы называют «терминал» или «консоль». А работает это так: мы вводим команду и получаем реакцию машины: сообщение об ошибке, запрос на подтверждение информации, результат выполненных действий.
Устанавливаем Git
Если раньше вы не работали с Git, сперва его нужно установить. Способы зависят от операционной системы вашего компьютера.
Установка в Linux
Используйте обычный менеджер пакетов вашего дистрибутива. Откройте терминал и введите подходящие команды.
- Если у вас 21 или более ранняя версия Fedora, используйте
yum install git
. - Для 22 и последующих версий Fedora вводите
dnf install git
. - Для дистрибутивов, основанных на Debian, например, Ubuntu, используйте
apt-get: sudo apt-get install git
.
Полный список команд для различных дистрибутивов можно посмотреть здесь.
Установка на macOS
- Скачиваем Git со страницы проекта.
- Запускаем загруженный файл.
- Система может показать окно с ошибкой, где будет написано, что файл скачан с неавторизованного сайта и инсталлятор не может быть запущен. В таком случае нужно зайти в «Системные настройки» — «Безопасность» (Security and Privacy), в появившемся окне будет сообщение об ошибке и кнопка Open anyway (Всё равно открыть). Нажимаем.
- Система покажет окно, уточняющее хотите ли вы запустить установку. Подтверждаем действие.
- Установщик проведёт через все необходимые шаги.
Установка в Windows
Скачайте exe-файл инсталлятора с сайта Git и запустите его. Это Git для Windows, он называется msysGit. Установщик спросит добавлять ли в меню проводника возможность запуска файлов с помощью Git Bash (консольная версия) и GUI (графическая версия). Подтвердите действие, чтобы далее вести работу через консоль в Git Bash. Остальные пункты можно оставить по умолчанию.
Проверим, что Git установлен
После того, как все действия по установке завершены, убедимся, что Git появился в системе компьютера. Откройте терминал и введите git --version
, должна появиться текущая версия программы на вашей машине. Эта проверка подходит для всех операционных систем.
Настройка Git
После того как Git появился на компьютере, нужно ввести свои данные, а именно имя и адрес электронной почты. Ваши действия в Git будут содержать эту информацию.
Откройте терминал и используйте следующую команду, чтобы добавить своё имя:
git config --global user.name "ваше имя"
Для добавления почтового адреса вводите:
git config --global user.email адрес
Обратите внимание, что в командах, указанных выше, есть опция --global
. Это значит, что такие данные будут сохранены для всех ваших действий в Git и вводить их больше не надо. Если вы хотите менять эту информацию для разных проектов, то в директории проекта вводите эти же команды, только без опции --global
.
Git — всему голова
А всё остальное — на интерактивных курсах по HTML, CSS и JavaScript. 11 глав сейчас и бесплатно.
РегистрацияНажатие на кнопку — согласие на обработку персональных данных
Регистрация на GitHub
Что такое GitHub?
GitHub — веб-сервис, который основан на системе Git. Это такая социальная сеть для разработчиков, которая помогает удобно вести коллективную разработку IT-проектов. Здесь можно публиковать и редактировать свой код, комментировать чужие наработки, следить за новостями других пользователей. Именно в GitHub работаем мы, команда Академии, и студенты интенсивов.
Чтобы начать работу с GitHub, нужно зарегистрироваться на сайте, если вы ещё этого не сделали. За дело.
- Переходим на сайт GitHub. Cтартовая страница GitHub.
- Для начала регистрации:
- Нажимаем кнопку Sign up (зарегистрироваться), попадаем на страницу регистрации, где вводим обязательные данные: имя пользователя, адрес электронной почты и пароль. После заполнения полей проходим верификацию. Первый шаг регистрации профиля на стартовой странице GitHub.
- После заполнения данных и успешного прохождения верификации нажимаем на кнопку Select a plan. Второй шаг регистрации профиля на стартовой странице GitHub.
- Третий шаг — небольшой опрос от GitHub, который вы можете пройти, заполнив все поля и нажать Submit или пропустить, нажав skip this step. Опрос на третьем шаге регистрации.
- После прохождения всех этапов на сайте, на указанный при регистрации ящик вам придёт письмо от GitHub. Откройте его и подтвердите свой почтовый адрес, нажав Verify email address (подтвердить электронный адрес) или скопируйте вспомогательную ссылку из письма и вставьте её в адресную строку браузера. Подтверждение электронного адреса.
- После верификации GitHub предложит создать новый репозиторий, организацию или узнать больше о GitHub. Этот пункт пока можно пропустить и перейти в профиль. Переход в ваш профиль.Так выглядит ваш профиль после регистрации.
Теперь у вас есть профиль на GitHub.
Устанавливаем SSH-ключи
Git установлен, профиль на GitHub создан. Осталось добавить SSH-ключ и можно приступать к работе с проектом.
Что такое SSH-ключ и зачем он нужен?
Чтобы работать со своего компьютера с GitHub, иметь доступ к проектам, хранящимся на сервисе, выполнять команды в консоли без постоянного подтверждения пароля, нужно пройти авторизацию у сервера. В этом помогают SSH-ключи.
Каждый SSH-ключ содержит пару: открытый (публичный) и закрытый (приватный) ключ. Открытый ключ отправляется на сервер, его можно не прятать от всех и не переживать, что кто-то его увидит и украдёт. Он бесполезен без своей пары — закрытого ключа. А вот закрытый ключ — секретная часть. Доступ к нему должен быть только у вас.
Вы отправляете какую-то информацию на сервер, где хранится ваш публичный ключ, сервер понимает, что вы это вы, то есть идентифицирует именно вас, и даёт вам какой-то ответ. И только вы можете расшифровать этот ответ, потому что только у вас есть подходящий закрытый ключ. Получается что-то вроде связки логин-пароль только намного безопасней. Ваш пароль кто-то может узнать или подобрать, а чтобы получить ваш приватный SSH-ключ, злоумышленнику придётся взломать ваш компьютер.
Чтобы пройти авторизацию по SSH-ключу, его надо сгенерировать или найти уже ранее созданный ключ на своём компьютере.
Сначала проверим, есть ли уже на компьютере ключ. По умолчанию SSH-ключи хранятся в каталоге ~/.ssh
, поэтому нужно проверить содержимое этого каталога.
- Открываем консоль.
- Вводим
cd ~/.ssh
, чтобы перейти в нужный каталог. Переходим в нужную директорию. - Используем
ls
, чтобы увидеть список всех файлов в каталоге. Открываем список файлов в директории. Ищем пару файлов с названиями видаимя
иимя.pub
. Обычно имя —id_rsa
,id_dsa
,id_ecdsa
илиid_ed25519
. Файл с расширением.pub
— ваш публичный ключ, а второй — ваш приватный, секретный ключ. Если таких файлов или даже каталога.ssh
у вас нет, вы можете их сгенерировать. Для этого делаем следующее. - Добавляем ключ в
ssh-agent
(сгенерированный или уже существующий). Проверяем доступность ключа командойeval "$(ssh-agent -s)"
и добавляем с помощьюssh-add ~/.ssh/your_key_name
, где указываем верный путь до файла с ключом и его имя. Добавляем ключ в shh-agent. Несколько важных примечаний:- Если вы захотите переименовать ключ, могут возникнуть проблемы. Их можно решить, добавив в
~/.ssh/config
связь ключа с доменом. - Если у вас Windows и вы пользуетесь программой Cmder, возможны проблемы с командой
eval "$(ssh-agent -s)"
. Может появиться такое сообщение об ошибке: «eval не является внутренней или внешней командой, исполняемой программой или пакетным файлом».В Сmder для запуска
ssh-agent
можно использовать командуstart-ssh-agent
.Если проблема осталась, рекомендуем работать в Git Bash.
- Если у вас macOS Sierra версии 10.12.2 и выше, нужно изменить ваш
~/.ssh/config
файл, чтобы автоматически загрузить ключи вssh-agent
и хранить пароли.Host * AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_rsa
Вы можете добавить свой приватный ключ в
ssh-agent
и сохранить пароль к нему с помощью командыssh-add -K ~/.ssh/id_rsa
. Если у вашего ключа другое имя, не забудьте заменитьid_rsa
в команде на правильное название. - Если у вас Linux, может понадобится переназначить для ~/.ssh права доступа командой
chmod 700 ~/.ssh/
- Если вы захотите переименовать ключ, могут возникнуть проблемы. Их можно решить, добавив в
- После того как создан ключ, его нужно добавить на GitHub. Для этого копируем его содержимое с помощью одной из следующих команд:
- Если вы на Windows
clip .
- Для пользователей macOS
pbcopy .
- На Linux используйте
sudo apt-get install xclip
, чтобы установить необходимый для копирования пакетxclip
, а затем введитеxclip -sel clip . Или введите команду
cat ~/.ssh/id_rsa.pub
, контент документа появится прямо в консоли и вы сможете скопировать ключ оттуда.
Можно пойти другим путём, открыть файл
id_rsa.pub
прямо в папке и просто скопировать содержимое оттуда. - Если вы на Windows
- Переходим на страницу для работы с ключами в вашем профиле на GitHub.
Страница с настройками ключей в вашем профиле.
Нажимаем кнопку New SSH key (новый SSH-ключ). Вводим имя ключа (можно придумать абсолютно любое) в поле Title (название), а в Key (ключ) вставляем сам ключ из буфера обмена. Теперь нажимаем Add SSH key (добавить SSH-ключ).
Добавляем в свой профиль SSH-ключ.Если всё сделано верно, в списке появится новый ключ.
Успешно добавленный ключ.
Теперь, наконец-то, мы можем начать работу с самим проектом.
Работа с репозиториями
Для начала определим, что такое репозиторий. Это рабочая директория с вашим проектом. По сути, это та же папка с HTML, CSS, JavaScript и прочими файлами, что хранится у вас на компьютере, но находится на сервере GitHub. Поэтому вы можете работать с проектом удалённо на любой машине, не переживая, что какие-то из ваших файлов потеряются — все данные будут в репозитории при условии, что вы их туда отправите. Но об этом позже.
Если над проектом трудится команда разработчиков, как правило, создаётся общий репозиторий, в котором находится рабочая версия проекта (назовём его мастер-репозиторий). При этом каждый пользователь клонирует себе в профиль оригинальный репозиторий и работает именно с копией. Такая копия называется форком. Так как форк — ваша персональная версия мастер-репозитория, в нём вы можете пробовать разные решения, менять код и не бояться что-то сломать в основной версии проекта.
Как сделать форк мастер-репозитория?
Заходим в нужный репозиторий, нажимаем на «вилку» с надписью fork. Форк репозитория создан и находится в вашем профиле на GitHub.
Теперь нужно склонировать форк себе на компьютер, чтобы вести работу с кодом локально. Тут нам и пригодится SSH.
Открываем консоль, переходим в директорию, где хотим сохранить папку с проектом, и вводим команду:
git clone [email protected]:your-nickname/your-project.git
Если вы правильно настроили SSH-ключи, Git начнёт процесс копирования репозитория на ваш компьютер. Если вы видите ошибку, в которой написано Error: Permission denied (publickey)
, скорее всего, вы ошиблись где-то при выполнении инструкции по настройке SSH-ключа. Вернитесь на несколько абзацев ранее и попробуйте повторить процесс настройки.
Если вы не хотите вручную вводить адрес репозитория, вы можете зайти на страницу проекта, нажать зелёную кнопку Clone or download (клонировать или скачать), выбрать Clone with SSH (клонировать по SSH) и скопировать адрес, который находится в текстовом поле. Этот адрес вы можете вставить в команду git clone
.
Кстати, если вы хотите, чтобы название папки с проектом у вас на компьютере отличалось от имени репозитория, можете дополнить команду клонирования, добавив в конце другое название:
git clone [email protected]:_your-nickname_/_your-project_.git folder_name
Теперь, на вашем компьютере, в папке your_project
или в той, название которой вы указали самостоятельно, находится полная копия репозитория c GitHub.
Чтобы начать работу с проектом, надо оказаться в его директории. Для этого используем команду cd
, после которой указываем название проекта на вашем компьютере: cd your-project
Работу над проектом принято вести в ветках. В каждом репозитории есть как минимум одна ветка. Это основная ветка, которую создаёт сам Git, она называется master
. Обычно в ней находится стабильная версия программы без ошибок. Если вы хотите исправить баг, добавить новую функциональность в проект, попробовать какую-то технологию, но не хотите сломать код в основной ветке, вы ответвляетесь из master
и трудитесь в своей новой ветке. Здесь вы можете реализовывать свои идеи, не переживая, что рабочий код сломается. Каждая ветка — что-то вроде второстепенной дороги, которая затем снова соединяется с основной.
Создадим новую ветку. Открываем терминал, вводим команду git branch
. Она показывает список веток, с которыми мы работаем в проекте, и выделяет текущую. Если мы находимся в master
создаём новую ветку:
git checkout -b имя-новой-ветки
.
Если текущая ветка не master
, сначала переключимся в основную ветку: git checkout master
. Мы делаем это, чтобы новая ветка содержала свежую, на момент создания, рабочую версию проекта.
Эта команда позволяет переключаться между существующими ветками в проекте, после git checkout
надо указать название нужной ветки.
Если вы ошиблись в названии, например, допустили опечатку, вы можете изменить название ветки с помощью команды: git branch -m старое-имя-ветки новое-имя-ветки
.
После того как вы создали ветку, поработали в ней у себя локально — нужно сохранить результат, чтобы он не пропал и в итоге оказался в репозитории.
Если вы хотите сохранить изменения не во всех файлах, для начала можно ввести команду git status
. Она покажет текущее состояние в вашей ветке, а именно список с названиями изменённых файлов, если они есть, и укажет на те, которые ожидают записи и сохранения (обычно они выделены красным цветом).
Перед тем, как зафиксировать изменения отдельных файлов, нужно добавить файлы в набор этих изменений. Воспользуйтесь командой git add имя-файла
. Если название очень длинное, вы можете начать его писать, затем нажать Tab и консоль сама предложит вам продолжение пути к файлу.
Если вы хотите сохранить все изменения разом, вводите git add -A
.
Теперь мы можем сделать коммит, то есть зафиксировать все сохранённые изменения и дать им название. Это делается с помощью команды git commit -m "ваше сообщение"
. Текст сообщения должен быть лаконичным и в то же время сообщать о том, что делает коммит (внесённые изменения). Например, «добавляет имя наставника в Readme», «вводит функцию сортировки изображений», «правит ошибку в поиске городов на карте».
Сохранения зафиксированы, всё? Они теперь в репозитории и видны коллегам? Пока нет. Те изменения, которые мы внесли и сохранили, пока локальны. Их нужно послать на GitHub.
Чтобы отправить свои изменения (коммиты) в репозиторий на GitHub, введите команду git push origin название-текущей-ветки
, где origin
означает репозиторий, который был склонирован на компьютер, то есть ваш форк.
Теперь заходим на страницу нашего форка и создаём пулреквест, чтобы слить свой код с данными в мастер-репозитории. Что такое пулреквест? Это предложение изменить код в репозитории.
Любое предложение можно принять или отвергнуть. Так же и с пулреквестом. После его создания, он должен получить ревью и одобрение так называемого коллаборатора — пользователя GitHub, который имеет права администратора в мастер-репозитории. Им может быть ваш коллега-разработчик, техлид, наставник. Если к вашему коду нет вопросов, пулреквест принимается и изменения из вашей ветки попадают в master
главного репозитория. Если в код нужно внести изменения, пулреквест отклоняется, и вам нужно снова пройти по цепочке локальные изменения — сохранение — коммит — пуш, только пулреквест заново делать не нужно. Если вы продолжаете вести работу в той же ветке и пулреквест ещё не принят, все ваши изменения автоматически добавятся в пулреквест, созданный из этой ветки после команды git push origin название-текущей-ветки
.
Вы исправили код, наставник или техлид одобрил ваши правки и принял пулреквест. Теперь код в мастер-репозитории обновился, а в вашем форке нет, вы ведь не обновляли свою версию репозитория с тех пор, как клонировали её себе на компьютер. Приведём форк в актуальное состояние.
- В локальном репозитории вводим команду
git checkout master
, переходим вmaster
. -
Теперь забираем (подтягиваем) изменения из ветки
master
мастер-репозиторияgit pull academy master
.Academy
здесь — сокращённое название мастер-репозитория, такое имя используется в проектах студентов Академии, вы можете выбрать любое другое название. Забираем изменения из мастер-репозитория. Если консоль выдаёт ошибку и говорит, что не знает директории с таким именем, нужно добавить ссылку на этот репозиторий:git remote add academy [email protected]:your-repo.git
Вместоacademy
указывайте своё название и оно закрепится за этим репозиторием. - Теперь отправьте изменения уже из своей ветки
master
в ваш форк на GitHub с помощью командыgit push origin master
. Отправляем изменения в форк.
Готово, теперь форк и оригинальный репозиторий находятся в актуальном состоянии.
руководство по использованию / Хабр
Rebase — один из двух способов объединить изменения, сделанные в одной ветке, с другой веткой. Начинающие и даже опытные пользователи git иногда испытывают нежелание пользоваться ей, так как не видят смысла осваивать еще один способ объединять изменения, когда уже и так прекрасно владеют операцией merge. В этой статье я бы хотел подробно разобрать теорию и практику использования rebase.Теория
Итак, освежим теоретические знания о том, что же такое rebase. Для начала вкратце — у вас есть две ветки — master и feature, обе локальные, feature была создана от master в состоянии A и содержит в себе коммиты C, D и E. В ветку master после отделения от нее ветки feature был сделан 1 коммит B.
После применения операции rebase master в ветке feature, дерево коммитов будет иметь вид:
Обратите внимание, что коммиты C’, D’ и E’ — не равны C, D и E, они имеют другие хеши, но изменения (дельты), которые они в себе несут, в идеале точно такие же. Отличие в коммитах обусловлено тем, что они имеют другую базу (в первом случае — A, во втором — B), отличия в дельтах, если они есть, обусловлены разрешением конфликтных ситуаций, возникших при rebase. Об этом чуть подробнее далее.
Такое состояние имеет одно важное преимущество перед первым, при слиянии ветки feature в master ветка может быть объединена по fast-forward, что исключает возникновение конфликтов при выполнении этой операции, кроме того, код в ветке feature более актуален, так как учитывает изменения сделанные в ветке master в коммите B.
Процесс rebase-а детально
Давайте теперь разберемся с механикой этого процесса, как именно дерево 1 превратилось в дерево 2?
Напомню, перед rebase вы находтесь в ветке feature, то есть ваш HEAD смотрит на указатель feature, который в свою очередь смотрит на коммит E. Идентификатор ветки master вы передаете в команду как аргумент:
git rebase master
Для начала git находит базовый коммит — общий родитель этих двух состояний. В данном случае это коммит A. Далее двигаясь в направлении вашего текущего HEAD git вычисляет разницу для каждой пары коммитов, на первом шаге между A и С, назовем ее ΔAC. Эта дельта применяется к текущему состоянию ветки master. Если при этом не возникает конфликтное состояние, создается коммит C’, таким образом C’ = B + ΔAC. Ветки master и feature при этом не смещаются, однако, HEAD перемещается на новый коммит (C’), приводя ваш репозитарий состояние «отделеной головы» (detached HEAD).
Успешно создав коммит C’, git переходит к переносу следующих изменений — ΔCD. Предположим, что при наложении этих изменний на коммит C’ возник конфликт. Процесс rebase останавливается (именно в этот момент, набрав git status вы можете обнаружить, что находитесь в состоянии detached HEAD). Изменения, внесенные ΔCD находятся в вашей рабочей копии и (кроме конфликтных) подготовлены к коммиту (пунктиром обозначена stage-зона):
Далее вы можете предпринять следующие шаги:
1. Отменить процесс rebase набрав в консоли
git rebase --abort
При этом маркер HEAD, будет перенесен обратно на ветку feature, а уже добавленные коммиты повиснут в воздухе (на них не будет указывать ни один указатель) и будут вскоре удалены.
2. Разрешить конфликт в вашем любимом merge-tool’е, подготовить файлы к коммиту, набрав git add %filename%
. Проделав это со всеми конфликтными файлами, продолжить процесс rebase-а набрав в консоли
git rebase --continue
При этом, если все конфликты действительно разрешены, будет создан коммит D’ и rebase перейдет к следующему, в данном примере последнему шагу.
3. Если изменения, сделанные при формировании коммита B и коммита D являются полностью взаимоисключающими, причем «правильные» изменения сделаны в коммите B, то вы не сможете продолжить набрав git rebase --continue
, так как разрешив конфликты обнаружите, что изменений в рабочей копии нет. В данном случае вам надо пропустить создание коммита D’, набрав команду
git rebase --skip
После применения изменений ΔDE будет создан последний коммит E’, указатель ветки feature будет установлен на коммит E’, а HEAD станет показывать на ветку feature — теперь, вы находитесь в состоянии на втором рисунке, rebase окончен. Старые коммиты C, D и E вам больше не нужны.
При этом коммиты, созданные в процессе rebase-а, будут содержать данные как об оригинальном авторе и дате изменений (Author), так и о пользователе, сделавшем rebase (Commiter):
commit 0244215614ce6886c9e7d75755601f94b8e19729 Author: sloot69 <***@****.com> AuthorDate: Mon Nov 26 13:19:08 2012 +0400 Commit: Alex <***@****.com> CommitDate: Mon Nov 26 13:33:27 2012 +0400
С небес на землю — rebase в реальных условиях
На самом деле обычно вы работаете не с двумя ветками, а с четырьмя в самом простом случае: master, origin/master, feature и origin/feature. При этом rebase возможен как между веткой и ее origin-ом, например feature и origin/feature, так и между локальными ветками feature и master.
Rebase ветки с origin-ом
Если вы хотите начать работать с rebase, то лучше всего начать с ребейза своих изменений в ветке относительно ее копии в удаленном репозитарии. Дело в том, что когда вы добавляете коммит, и в удаленном репозитарии добавляется коммит, для объединения изменений по-умолчанию используется merge. Выглядит это примерно так:
Представим умозрительную ситуацию — 3 разработчика активно работают с веткой master в удаленном репозитарии. Делая одновременно комиты на своих машинах они отправляют каждый по 1 изменению в ветку. При этом первый отправляет их без проблем. Второй и третий сталкивается с тем что ветка не может быть отправлена операцией git push origin master
, так как в ней уже есть изменения, которые не синхронизированы на локальные машины разработчиков. Оба разработчика (2 и 3) делают git pull origin master
, создавая при этом локальные merge-коммиты у себя в репозитарии. Второй делает git push первым. Третий при попытке отправить изменения снова сталкивается с обновлением удаленной ветки и снова делает git pull, создавая еще один merge-коммит. И наконец, третий разработчик делает успешный git push origin master
. Если удаленный репозитарий расположен например на github, то network, то есть граф коммитов будет иметь следующий вид:
Три коммита превратились в 6 (базовый коммит не считаем), история изменений неоправдано запутана, информация об объединении локальных веток с удаленными, на мой взгляд, лишняя. Если масштабировать эту ситуацию на несколько тематических веток и большее количество разработчиков, граф может выглядеть, например, так:
Анализ изменений в таком графе неоправданно трудоемкое занятие. Как тут может помочь rebase?
Если вместо git pull origin master
выполнить git pull --rebase origin master
, то ваши локальные изменения, подобно коммитам C, D и E из первого примера будут перенесены наверх обновленного состояния ветки origin/master, позволяя без создания дополнительных коммитов передать их на удаленный сервер с помощью git push origin master
. То есть слияние изменений будет выглядеть уже так:
Как видно, «лишних» merge-коммитов создано не было, ваши изменения в коммите C были использованы для создания коммита C’. Сам же коммит C остался у вас в локальном репозитарии, в удаленный репозитарий был передан только C’. Если все программисты в команде возьмут за правило пользоваться git pull --rebase
, тогда каждая из веток в удаленном репозитарии будет выглядеть линейно.
Как поделиться веткой, к которой применен rebase, с коллегой
Подробно процесс rebase-а локальной тематической ветки отосительно ветки master был рассмотрен в самом начале статьи. Оговорюсь только, что процесс rebase содержит количество шагов равное количеству коммитов в вашей локальной ветке. Вероятность потенциальных конфликтов, как и в случае с merge, растет пропорционально росту количества коммитов в базовой ветке (master). Поэтому лучше периодически проводить rebase для долгоживущих тематических веток. Но если тематическая ветка имеет свой оригинал на удаленном сервере, как передать ветку в удаленный репозитарий? Если делать push можно только для изменений, которые могут быть приняты по fast-forward, а в данном случае, как мы знаем, это не так:
Тут все просто, наберите в консоли команду:
git push origin feature --force
Force-режим просто копирует отсутствующие родительские коммиты ветки feature на origin и насильно устанавливает указатель ветки на тот же коммит, что и ваш локальный.
Будьте внимательны! Если вы забудете указать идентификатор ветки, то force-push будет выполнен для всех локальных веток, имеющих удаленный оригинал. При этом нужно понимать, что некоторые локальные ветки могут быть в неактуальном состоянии. То есть измененения, которые вы не успели затянуть будут удалены в origin-е. Конечно, сами коммиты не будут удалены — сбросятся только указатели ветки. Эта ситуация поправима — достаточно для каждой ветки найти человека, который последним пушил изменения в нее или уже успел их забрать. Он может сделать обычный push, вновь передав их на origin. Но вся эта морока вам ни к чему, так что лучше просто будьте внимательны.
Ваш коллега, находится в той же ситуации перед pull, в которой вы находились перед тем как сделали push. Только позиции feature и origin/feature отличаются с точностью до наоборот. Если он выполнит обычный git pull origin feature
, то произойдет попытка объединения старой и новой ветки с помощью merge. Так как старая и новая ветки содержат одни и те же изменения, то все они будут конфликтными. В данном случае нам снова поможет команда:
git pull --rebase origin feature
Она заберет новую ветку feature и переместит локальные изменения вашего коллеги на ее вершину.
Вообще
git pull --rebase origin feature
— это безпроигрышный вариант, так как если rebase не требуется, произойдет обычное объединение указателей по fast-forward.Реинтеграция тематической ветки в master
Мы рассмотрели все необходимые операции для работы с ветками в стиле rebase. Осталось только переключиться в ветку master и сделать git merge feature. Ветка, подготовленная rebase-ом вольется в master по fast-forward, то есть указатель будет просто перемещен вперед.
Однако, у такого подхода есть один недостаток — после merge по fast-forward будет затруднительно определить, какие коммиты были сделаны в вашей ветке, а какие в другой ветке, влитой перед вашей или непосредственно в мастере. Хорошим тоном может быть принятие в вашей команде правила — при интеграции изменений из тематической ветки в основную применять операцию merge с опцией —no-ff. При этом будет создан merge-коммит, одним из родителей которого будет позиция ветки master, другим — позиция ветки feature. Сравните граф коммитов, при объединении веток по fast-forward (слева) и c merge-коммитами, полученными с помощью опции —no-ff (справа):
В данном случае, на мой взгляд, merge-коммиты полезны и несут в себе информацию о моменте объединения веток. Этот граф выглядит как учебный пример, но такая структура вполне реальна при соблюдении некоторых простых правил всеми членами команды.
Заключение
Мы видим, что читаемость графа изменений может быть улучшена на порядок при соблюдении нескольких простых правил, хотя они и требуют небольших дополнительных временных затрат.
В официальном руководстве по git крайне не рекомендуют применять rebase к ветке, которая была запушена в публичный репозитарий, приводятся проблемы, связанные с merge-ем старой ветки, к которой еще не применен rebase (хранящейся у кого-то, кто успел ее загрузить из репозитария) и новой ветки, что приводит к конфликтам и появлению коммитов с одинаковыми датами и сообщениями в логе изменений, здесь мы рассмотрели, как легко можно избежать этой проблемы с помощью git pull —rebase.
В данной статье сделано одно допущение. Все это верно при простой модели ветвления — есть одна главная ветка master и несколько тематических, которые создаются от нее. Когда от тематической ветки создается другая тематическая ветка, есть свои нюансы при rebase-е первичной и вторичной ветки. О них можно прочитать в том самом официальном руководстве.
Иногда споры, что же лучше merge или rebase доходят до холивара. От себя могу сказать, что в конечном счете выбор за вами, однако этот выбор не может быть продиктован уровнем владения тем или иным инструментом. Обоснованный выбор можно сделать, только когда для вас не составит труда работать и в том и в другом стиле. Я не агитирую за повсеместное использование rebase-а, а просто объясняю как им пользоваться. Надеюсь, это статья поможет вам снять вопросы, связанные с механизмом работы rebase и его применением в ежедневной работе.
PS. Хочу поблагодарить своих коллег, продуктивные беседы с которыми позволили мне лучше разобраться в материале, положенном в основу этой статьи.
Моя шпаргалка по работе с Git
Некоторое время назад я открыл для себя Git. И знаете, я проникся. То есть, по-настоящему проникся. Теперь я использую Git не только на работе (где я с ним, собственно, познакомился), но и для своих проектиков, которые я стал хранить на BitBucket. Последний начал поддерживать Git относительно недавно. В отличие от GitHub, BitBucket позволяет совершенно бесплатно создавать как открытые, так и закрытые репозитории.
В чем состоит отличие Git от Subversion?
Главное отличие Git от Subversion заключается в том, что Git — распределенная система контроля версий. Звучит ужасающе, но на практике это означает очень простую вещь. Каждый разработчик держит у себя на диске отдельный репозиторий. Обратите внимание — не копию репозитория, не некоторые бранчи, а тупо отдельный и при этом абсолютно полноценный репозиторий.
Пока мы работаем в рамках своего репозитория, все происходит в точности, как в Subversion. Мы коммитим и откатываем изменения, создаем, мержим и удаляем бранчи, разрешаем конфликты и тд. Помимо этого, предусмотрены команды для работы с репозиториями на удаленных машинах. Например, «git push» означает мерж локальных изменений в удаленный репозиторий, а «git pull» — наоборот, мерж изменений из удаленного репозитория в локальный. Обмен данными по сети обычно происходит с использованием протокола SSH.
В результате имеем:
- Git присущи все те же преимущества от использования VCS, что мы получаем в Subversion.
- Git дает нам нормальное шифрование «из коробки», безо всяких танцев с бубнами, как в случае с Subversion.
- Если сервер с «главным» репозиторием, куда пушат свои изменения все разработчики (хотя формально в Git нет никакого «главного» репозитория), вдруг прилег — ничего страшного. Делаем коммиты в локальный репозиторий и ждем, когда сервер вернется.
- Даже если сервер доступен, все равно удобнее сделать пяток локальных коммитов, а затем отправить их на сервер одним пушем.
- Сервер вообще не нужен. Вы можете использовать Git только локально. И не обязательно для работы с исходниками. Например, можно использовать Git для того, чтобы иметь возможность откатиться к предыдущим версиям файлов (каких-нибудь электронных таблиц) или вернуть случайно удаленные.
- Git не раскидывает по каталогам служебную информацию (помните «.svn»?), вместо этого она хранится только в корне репозитория.
- Git нынче очень моден (хотя это далеко не единственная распределенная система контроля версий, например, есть Mercurial и Darcs), в связи с чем растет число разработчиков, использующих его. Как следствие, используя Git, легче получить помощь на каком-нибудь форуме или собрать команду разработчиков, знакомых с этой VCS.
- Существует множество полезных утилит для работы с Git — Qgit, gitk, gitweb и другие. «Из коробки» есть импорт и экспорт в/из Subversion/CVS.
- Git поддерживают многие хостинги репозиториев (GitHub, BitBucket, SourceForge, Google Code, …) — есть из чего выбрать.
- Большой популярностью пользуется GitHub. Используя Git, вы увеличиваете вероятность того, что кто-то захочет безвозмездно написать патч для вашего open source проекта.
Пример использования Git
Я использовал Git при написании программы из заметки Генерация почти осмысленных текстов на Haskell, сидя под своей любимой FreeBSD. Вот как примерно выглядела моя работа с Git.
В первую очередь необходимо поставить Git:
Затем создаем пару ssh ключей, если не создавали ее ранее:
ssh-keygen
cat ~/.ssh/id_rsa.pub
Заходим на БитБакет, создаем git-репозиторий под новый проект, а в свойствах аккаунта прописываем свой открытый ssh-ключ. Затем клонируем репозиторий:
cd ~/projects/haskell
git clone [email protected]:afiskon/hs-textgen.git
cd hs-textgen
Делаем какие-то изменения:
Добавляем новый файл в репозиторий и делаем коммит:
git add TODO.TXT
git commit -a
Поскольку я не указал описание коммита, запускается редактор VIM, с помощью которого я и ввожу описание. Затем я отправляю все сделанные мною изменения на БитБакет:
Допустим, теперь я хочу сделать некоторые изменения в проекте, но не уверен, выйдет ли из этого что-то хорошее. В таких случаях создается новая ветка:
git branch new_feature
git checkout new_feature
Работаем с этой веткой. Если ничего хорошего не вышло, возвращаемся к основной ветке (она же «trunk» или «ствол»):
Если вышло что-то хорошее, мержим ветку в master (о разрешении конфликтов рассказано в следующем параграфе):
git commit -a # делаем коммит всех изменений в new_feature
git checkout master # переключаемся на master
git merge new_feature # мержим ветку new_feature
Не забываем время от времени отправлять наш код на BitBucket:
Если мы правим код с нескольких компьютеров, то перед началом работы не забываем «накатить» в локальный репозиторий последнюю версию кода:
Работа в команде мало чем отличается от описанного выше. Только каждый программист должен работать со своей веткой, чтобы не мешать другим программистам. Одна из классических ошибок при начале работы с Git заключается в push’е всех веток, а не только той, с которой вы работали. Вообще я бы советовал первое время перед выполнением каждого push делать паузу с тем, чтобы подумать, что и куда сейчас уйдет. Для большей безопасности советую при генерации ssh-ключей указать пароль. Тогда каждый запрос пароля со стороны Git будет для вас сигналом «Эй, ты делаешь что-то, что затронет других».
Fun fact! Нравится статья? Поддержи автора, чтобы он мог писать больше полезных статей!
Для работы с Git под Windows можно воспользоваться клиентом TortoiseGit. Если память не подводит, для работы ему нужен Git for Windows. Для генерации ключей можно воспользоваться утилитой PuTTyGen. Только не забудьте экспортировать открытый ключ в правильном формате, «Conversions → Export OpenSSH key».
Следует отметить, что мне лично TortoiseGit показался не слишком удобным. Возможно, это всего лишь дело привычки, но мне кажется намного удобнее работать с Git из консоли, чем с помощью контекстного меню в Проводнике.
Шпаргалка по командам
В этом параграфе приведена сухая шпаргалка по командам Git. Я далеко не спец в этой системе контроля версий, так что ошибки в терминологии или еще в чем-то вполне возможны. Если вы видите в этом разделе ошибку, отпишитесь, пожалуйста, в комментариях.
Создать новый репозиторий:
Если вы планируете клонировать его по ssh с удаленной машины, также скажите:
git config —bool core.bare true
… иначе при git push вы будете получать странные ошибки вроде:
Refusing to update checked out branch: refs/heads/master
By default, updating the current branch in a non-bare repository
is denied, because it will make the index and work tree inconsistent
with what you pushed, and will require ‘git reset —hard’ to match
the work tree to HEAD.
Клонировать репозиторий с удаленной машины:
git clone [email protected]:afiskon/hs-textgen.git
Если хотим пушить один код в несколько репозиториев:
git remote add remotename [email protected]:repo.git
Добавить файл в репозиторий:
Удалить файл:
Текущее состояние репозитория (изменения, неразрешенные конфликты и тп):
Сделать коммит:
git commit -a -m «Commit description»
Сделать коммит, введя его описание с помощью $EDITOR:
Замержить все ветки локального репозитория на удаленный репозиторий (аналогично вместо origin можно указать и remotename, см выше):
Аналогично предыдущему, но делается пуш только ветки master:
Запушить текущую ветку, не вводя целиком ее название:
Замержить все ветки с удаленного репозитория:
Аналогично предыдущему, но накатывается только ветка master:
Накатить текущую ветку, не вводя ее длинное имя:
Скачать все ветки с origin, но не мержить их в локальный репозиторий:
Аналогично предыдущему, но только для одной заданной ветки:
Начать работать с веткой some_branch (уже существующей):
git checkout -b some_branch origin/some_branch
Создать новый бранч (ответвится от текущего):
Переключиться на другую ветку (из тех, с которыми уже работаем):
Получаем список веток, с которыми работаем:
git branch # звездочкой отмечена текущая ветвь
Просмотреть все существующие ветви:
git branch -a # | grep something
Замержить some_branch в текущую ветку:
Удалить бранч (после мержа):
git branch -d some_branch
Просто удалить бранч (тупиковая ветвь):
git branch -D some_branch
История изменений:
История изменений в обратном порядке:
История конкретного файла:
Аналогично предыдущему, но с просмотром сделанных изменений:
История с именами файлов и псевдографическим изображением бранчей:
Изменения, сделанные в заданном коммите:
git show d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4
Посмотреть, кем в последний раз правилась каждая строка файла:
Удалить бранч из репозитория на сервере:
git push origin :branch-name
Откатиться к конкретному коммиту (хэш смотрим в «git log»):
git reset —hard d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4
Аналогично предыдущему, но файлы на диске остаются без изменений:
git reset —soft d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4
Попытаться обратить заданный commit:
git revert d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4
Просмотр изменений (суммарных, а не всех по очереди, как в «git log»):
git diff # подробности см в «git diff —help»
Используем vimdiff в качестве программы для разрешения конфликтов (mergetool) по умолчанию:
git config —global merge.tool vimdiff
Отключаем диалог «какой mergetool вы хотели бы использовать»:
git config —global mergetool.prompt false
Отображаем табы как 4 пробела, например, в «git diff»:
git config —global core.pager ‘less -x4’
Создание глобального файла .gitignore:
git config —global core.excludesfile ~/.gitignore_global
Разрешение конфликтов (когда оные возникают в результате мержа):
Создание тэга:
git tag some_tag # за тэгом можно указать хэш коммита
Удаление untracked files:
«Упаковка» репозитория для увеличения скорости работы с ним:
Иногда требуется создать копию репозитория или перенести его с одной машины на другую. Это делается примерно так:
mkdir -p /tmp/git-copy
cd /tmp/git-copy
git clone —bare [email protected]:afiskon/cpp-opengl-tutorial1.git
cd cpp-opengl-tutorial1.git
git push —mirror [email protected]:afiskon/cpp-opengl-tutorial2.git
Следует отметить, что Git позволяет использовать короткую запись хэшей. Вместо «d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4» можно писать «d8578edf» или даже «d857».
Дополнение: Также в 6-м пункте Мини-заметок номер 9 приводится пример объединения коммитов с помощью git rebase
, а в 10-м пункте Мини-заметок номер 11 вы найдете пример объединения двух репозиториев в один без потери истории.
Работа с сабмодулями
Более подробно сабмодули и зачем они нужны объясняется в заметке Простой кроссплатформенный OpenGL-проект на C++. Здесь упомянем самое главное.
Добавить сабмодуль:
git submodule add https://github.com/glfw/glfw glfw
Инициализация сабмодулей:
Обновление сабмодулей, например, если после git pull
поменялся коммит, на который смотрит сабмодуль:
Удаление сабмодуля производится так:
- Скажите
git rm --cached имя_сабмодуля
; - Удалите соответствующие строчки из файла .gitmodules;
- Также грохните соответствующую секцию в .git/config;
- Сделайте коммит;
- Удалите файлы сабмодуля;
- Удалите каталог .git/modules/имя_сабмодуля;
Дополнительные материалы
В качестве источников дополнительной информации я бы рекомендовал следующие:
Как обычно, любые замечания, дополнения и вопросы категорически приветствуются. И кстати, с наступающим вас!
Дополнение: Практика работы с системами контроля версий
Метки: Разработка.
Git — это широко используемый децентрализованный репозиторий исходного кода. Он был создан создателем Linux Линусом Торвальдсом для управления исходным кодом ядра Linux. Целые сервисы, такие как GitHub, основаны на нем. Он даже используется в IBM DevOps Services вместе с хранилищем исходного кода IBM Rational Team Concert ™. Поэтому, если вы хотите программировать в мире Linux или использовать DevOps Services от IBM с Git, это поможет вам лучше понять Git.
Когда я начал работать с Git, у меня был некоторый опыт работы с Concurrent Versions System (CVS) и Apache Subversion (SVN), поэтому я попытался понять это с точки зрения этих классических систем репозитория исходного кода. Такое мышление только дало мне ограниченное понимание возможностей Git. С тех пор я стал гораздо лучше понимать Git, поэтому эта статья является своего рода «примечанием к себе», которое напоминает мне о том, как работает Git, и объясняет его новичкам. Я предполагаю, что вы знакомы с другими более классическими репозиториями исходного кода, такими как CVS или SVN.
Основы
Итак, давайте начнем с базового примера в классическом хранилище исходного кода, как на рисунке 1. В классическом хранилище исходного кода папка с файлами и подпапками обрабатывается как содержимое (CVS и Git фактически не обрабатывают папки Просто файлы в пути пути). В репозитории хранятся все версии контента, а рабочий каталог — это место, где вы модифицируете код. Вы извлекаете код из репозитория в рабочий каталог и фиксируете изменений, которые вы сделали в этом рабочем каталоге, обратно в новую версию содержимого в репозитории.
Рисунок 1. Классическая обработка рабочей области хранилища исходного кода
Каждый коммит создает новую дочернюю версию контента, которая наследуется от предыдущей родительской версии , которую вы изменили, как показано на рисунке 2. Контент хранится в виде серии версий, также называемых снимками , связанными Родительско-дочерние отношения, созданные операциями фиксации. Информация, которая изменилась между родительской и дочерней версией при фиксации, называется набором изменений .
Эта серия версий называется stream или branch . В SVN основной поток называется транком ; в CVS он обычно называется HEAD ; в Git его обычно называют , мастер . Ветви используются в проекте внедрения, чтобы отделить разработку определенной функции или для поддержки более старой версии.
Рисунок 2. Создание новой версии в классическом репозитории
Пока что Git очень похож на такие классические репозитории исходного кода, не так ли? К сожалению, на этом сходство заканчивается.Одной из основных особенностей CVS и SVN является то, что они имеют центральное хранилище. Git децентрализован. Несколько репозиториев могут работать вместе при разработке программного обеспечения и фактически работают так, как репозиторий каждого разработчика работает и взаимодействует так же, как и любой серверный репозиторий Git.
Как работает Git
Главный принцип Git, когда вы его понимаете, удивительно прост.
Во-первых, Git обрабатывает содержимое в снимках, по одному на каждый коммит, и знает, как применить или откатить наборы изменений между двумя снимками.Это важная концепция. На мой взгляд, понимание концепции применения и отката наборов изменений значительно упрощает понимание и работу с Git.
Это настоящий основной принцип. Все остальное следует из этого. Итак, давайте углубимся в Git.
Работа с Git
git init — инициализирует репозиторий.
git checkout — извлекает ветку из репозитория в рабочий каталог.
git add — добавляет изменение файла в набор изменений.
git commit — фиксирует набор изменений из рабочего каталога в хранилище.
Чтобы начать работать с Git, вам нужно просто выполнить команду git init
. Он превращает текущий каталог в рабочий каталог Git и создает репозиторий в каталоге .git
(скрытом), который он там создает. Затем вы можете начать работать с Git. Команды checkout
и commit
аналогичны другим репозиториям исходного кода, но внимание к наборам изменений является причиной того, что в Git у вас есть команда add
(аналогично SVN).С помощью этой команды изменение в рабочем каталоге добавляется в промежуточную область для следующего коммита. Эта область подготовки обычно называется индексом . На рисунке 3 показан процесс создания набора изменений из версии снимка A в версию снимка B.
git status
помогает отслеживать, какие изменения были добавлены или нет, в какой ветке вы находитесь.
Рисунок 3. Создание набора изменений в Git
git log
показывает историю изменений (т.е.е. фиксирует) в рабочем каталоге или с git log <путь>
изменения, примененные к данному пути.
Несмотря на то, что git status
перечисляет измененные файлы в рабочей области, а также файлы в индексе, вы можете посмотреть на различия между файлами с помощью команды git diff
. Просто использование git diff
(без параметров) показывает только те изменения в рабочем каталоге, которые еще не были добавлены в индекс. Вам нужно использовать git diff --cached
, чтобы увидеть, что на самом деле в индексе: поэтапные изменения. git diff <имя>
или git diff <имя> - <путь>
показывает разницу между текущим рабочим каталогом и именованным коммитом для рабочего каталога или заданного пути соответственно. Имя может быть идентификатором фиксации, именем ветви или другим именем. Это хорошее время, чтобы поговорить о наименовании.
Наименование
Примечание:
Из-за длины идентификаторов фиксации я буду использовать в диаграммах только такие сокращения, как «(A)», «(B)» и т. Д.
Давайте посмотрим на названия вещей в Git. Снимки являются основными элементами в Git. Они названы с идентификатором фиксации , который представляет собой хеш-код, например, «c69e0cc32f3c1c8f2730cade36a8f75dc8e3d480». Он получен из содержимого снимка, который включает в себя фактическое содержимое и некоторые метаданные, такие как время отправки, информацию об авторе, родители и т. Д. Снимок не имеет версии с точечным номером , как в CVS, или транзакции номер (и путь в каталоге / branch top) как в SVN.Из-за этого вы не можете определить какой-либо порядок по именам снимков Git, как в других репозиториях. Git может для удобства сокращать эти длинные хэши до коротких имен, беря минимальное количество символов от начала идентификатора, так что короткое имя по-прежнему уникально в репозитории. В приведенном выше примере короткое имя «c69e0cc».
Обратите внимание, что термин commit используется как в качестве глагола для создания снимка, так и в качестве имени для полученного снимка.
Обычно вам не нужно работать с идентификаторами коммитов; вместо этого вы работаете с филиалами. Именованный поток изменений в других хранилищах исходного кода называется ветвью. В Git поток изменений представляет собой упорядоченный список наборов изменений, поскольку они применяются один за другим для перехода от одного снимка к следующему. Ветвь в Git — это только именованный указатель на определенный снимок. Это отмечает место, где новые изменения должны быть применены, когда эта ветвь используется. Когда изменение применяется к ветви, метка ветви также перемещается в новый коммит.
Как Git узнает, где поместить изменения из рабочей области? Именно на это указывает HEAD. Главой разработки является то место, где вы в последний раз проверяли свое рабочее пространство и, что более важно, куда вносить изменения. Обычно это указывает на ветку, которую вы последний раз проверяли. Обратите внимание, что это отличается от того, как CVS интерпретирует термин HEAD как совет развития ветки по умолчанию.
Команда tag
называет коммит и позволяет адресовать отдельный коммит с читаемым именем.2 второй и тд.
Для получения более подробной информации смотрите главную страницу gitrevisions . Поскольку имена, такие как теги или имена ветвей, являются ссылками на коммиты, они называются именами рефлексов . reflog показывает, что изменилось за время существования имени, с момента его создания (обычно ветвью) до текущего состояния.
Ветвление
Концепция ветвления заключается в том, что у каждого снимка может быть несколько дочерних элементов. Применение второго набора изменений к тому же снимку создает новый, отдельный поток разработки.И если он назван, он называется ветвью.
Рисунок 4. Пример структуры ветви в Git
Рисунок 4 иллюстрирует это на примере структуры ветвей в Git. Ветвь master , в которой происходит некоторая разработка, указывает на снимок F . Другая ветвь , старая , отмечает более старый снимок, возможно, возможную точку исправления. Функция В ветви есть другие изменения для определенной функции. Наборы изменений отмечаются как переход от одной версии к другой, например «[B-> D]».В этом примере снимок B имеет двух дочерних элементов, оттуда идут два потока разработки, один для ветви функций и один для остальных. Коммит А также помечен как исправляющий ошибку № 123.
git branch — создает новую ветку из текущего HEAD (рабочий каталог).
git checkout -b — создает новую ветку из текущего HEAD и переключает рабочий каталог на новую ветку.
git diff — — показывает разницу между рабочим каталогом и данной веткой.
git checkout — — извлекает файлы из данной ветки в рабочий каталог.
git merge — объединяет данную ветку с текущей веткой.
git merge -abort — прерывает слияние, которое привело к конфликтам.
Ветви создаются с помощью команды git branch <имя-ветви>
в текущем HEAD или ветки git <имя-ветви> <идентификатор_мита>
в любой допустимой версии снимка.Это создает новый указатель ветки в хранилище. Будьте осторожны, ветвление таким образом оставляет ваше рабочее пространство в старой ветке. Сначала вам нужно оформить заказ на новую ветку. С помощью git checkout -b <имя ветви>
создается новая ветка, и ваше рабочее пространство также перемещается в новую ветку.
Две другие команды довольно полезны:
-
git diff
, как уже упоминалось выше, печатает diff данного пути (файла или каталога) между текущим рабочим каталогом и указанной ветвью.- -
git checkout
извлекает файлы из другой ветви в рабочий каталог, чтобы вы могли выбирать изменения из другой ветви.-
Слияние
Когда вы реализовали свою новую функцию, вы зарегистрировали ее в репозитории, например, в своей ветке «Feature». Когда функция завершена, вам нужно объединить ее обратно в основную ветку. Вы делаете это, проверяя основную ветку, и используете git merge <имя ветви>
.Затем Git объединяет изменения из данной ветви с извлеченной веткой. Для этого Git применяет все наборы изменений из ветви функций на кончике главной ветви.
В зависимости от типа изменений в двух ветвях и возможных конфликтов, возможны три варианта.
Ускоренное слияние : получающая ветвь не получила никаких изменений, так как две ветки разошлись. Принимающая ветвь все еще указывает на последний коммит до того, как другая ветвь разошлась.В этом случае Git перемещает указатель ветви приемной ветви вперед, как показано на рисунке 5. Поскольку ничего не нужно делать, кроме перемещения указателя ветви вперед, Git называет это слиянием быстрой перемотки вперед.
Рисунок 5. Быстрое слияние вперед
Бесконфликтное объединение : есть изменения в обеих ветвях, но они не конфликтуют. Это происходит, например, если изменения в обеих ветках влияют на разные файлы. Git может автоматически применить все изменения из другой ветви в ветку-получателя и создать новый коммит с этими изменениями.Получающая ветвь затем перемещается вперед к этой фиксации, как показано на рисунке 6.
Обратите внимание, что в результате фиксации, фиксация слияния имеет двух родителей. Я не заметил здесь наборы изменений. В принципе, набор изменений с (E) на (H) был бы комбинацией всех наборов изменений из ветви признаков с момента отклонения двух ветвей, но это, вероятно, слишком далеко заходит по аналогии.
Рисунок 6. Бесконфликтное слияние
- Конфликтующее слияние : в обеих ветках есть изменения, но они конфликтуют.В этом случае противоречивый результат остается в рабочем каталоге, чтобы пользователь мог исправить и зафиксировать его или прервать слияние с помощью
git merge –abort
.
Следует отметить одну интересную вещь: объединение находит случаи, когда один и тот же патч был применен в обеих ветвях. Поскольку у вас есть изменения в обеих ветках, это обычно приводит к конфликту, но, поскольку Git достаточно умен, чтобы обнаружить эту ситуацию, вы все равно можете выполнить слияние в ускоренном режиме.
Концепция отката и воспроизведения наборов изменений продолжает развиваться благодаря дополнительным функциям, таким как , перебирающий и , собирающим вишню .
Иногда вы разрабатываете функцию, но основная разработка также идет параллельно, и вам пока не нужно объединять эту функцию. Следствием этого будет то, что две ветви удаляются друг от друга довольно быстро. Однако можно применять наборы изменений из одной ветви в другую. Для этого Git предлагает ребаз и функцию сбора вишни.
Ребазинг
Представьте, что вы разрабатываете свою функцию и вам необходимо включить последние изменения из основной ветки, чтобы идти в ногу с общей разработкой.Это называется , перебазируя вашей функциональной ветки; это перемещает точку отклонения между двумя ветвями вверх на одной из ветвей. Что делает Git, так это то, что он воспроизводит изменения из одной ветви поверх кончика другой ветви, создавая новые коммиты для каждого из оригинальных коммитов. В примере, показанном на рисунке 7, он пытается применить изменения из ветви функций поверх главной ветви.
Рисунок 7. Перебазирование ветки
git rebase — перебрасывает вашу текущую ветку на верхушку данной другой ветви.
git rebase -i — интерактивная перебазировка.
git cherry-pick — прерывает выбор вишни, приводящий к конфликтам.
git revert — восстанавливает патч.
Если воспроизведение приводит к конфликту, rebase останавливается при первом конфликте и оставляет конфликтующее состояние в рабочем каталоге для исправления пользователем. Затем ребаз может быть продолжен или прерван.
С опцией --onto
, ребаз может фактически переместить точку отклонения «на» любой более новый снимок в другой ветви.
Сбор вишни
Представьте, что вы сейчас работаете над функцией и разработали некоторые изменения, которые должны быть немедленно внесены в вашу основную разработку. Это может быть исправление ошибки или отличная функция, но вы еще не хотите объединять или перемещать ветви. Git позволяет копировать набор изменений из одной ветви в другую, используя функцию выбора вишни.
В этой ситуации, как показано на рисунке 8, Git просто применяет набор изменений, ведущий к выбранному снимку в HEAD, скажем, в основной ветви.Здесь вы обычно используете идентификатор фиксации, также известный как хэш-значение.
Рисунок 8. Вишня выбирает коммит
Вернуть
Команда revert
откатывает один или несколько наборов исправлений в рабочем каталоге, а затем создает новый коммит для результата. Revert
— это почти противоположность вишневому кирке. Смотрите рисунок 9 для примера.
Рисунок 9. Возврат коммита
Команда revert
документирует возврат как новый коммит.Если вы не хотите, чтобы это было задокументировано, вы можете сбросить указатель ветки на более ранний коммит, но это выходит за рамки данной статьи.
Так почему я прошел этот раздел так подробно? Это потому, что важно понимать эти функции при обсуждении функций совместной работы в следующем разделе. Фактически, как только вы поймете этот первый раздел, второй раздел будет почти сразу понятен. Большая часть функциональности совместной работы основана на базовой функциональности, обсуждавшейся до сих пор.
Сотрудничество
В классических хранилищах исходного кода всегда есть четкое представление о том, что такое ветвь; это тот, что в центральном хранилище.
Однако в Git нет такой вещи, как главная ветвь. Подождите, разве я не написал выше, что обычно есть главная ветка? Да, я сделал. Тем не мение. Эта основная ветвь существует только локально. Между главной ветвью в одном репозитории и той, что в другом репозитории, нет никакой связи, за исключением отношения, которое вы создаете.
Рисунок 10. Два хранилища
Если у вас уже есть репозиторий, вы можете добавить удаленные репозитории с помощью команды git remote add
. Затем вы можете получить зеркало удаленной ветви в своем собственном репозитории с помощью команды fetch
. Это называется ветвью удаленного отслеживания , поскольку она отслеживает развитие в удаленной системе.
Когда вы извлекаете ветку, которая существует только как удаленная ветвь отслеживания (но не как локальная ветвь), Git автоматически создает локальную ветку из удаленной ветки отслеживания и проверяет эту.
Получив это, вы можете объединить содержимое удаленной ветви с вашей собственной веткой. На рисунке 11 показана проверка в локальной ветке master, но в этом нет необходимости, вы можете объединить ее с любой другой ветвью с общей историей, такой как обычная команда merge.
Рисунок 11. Извлечение и проверка удаленного филиала
Альтернативой является команда git clone
, которая получает удаленный репозиторий, например, из службы хостинга.Это автоматически получает все удаленные ветви (но еще не локальные ссылки) и проверяет основную ветку.
Как видите, картина возникает. Поскольку ветвь удаленного репозитория является «просто ветвью», все, что обсуждалось выше относительно ветвления, слияния и т. Д., Применяется практически без проблем, особенно при получении изменений из удаленного репозитория.
Рисунок 12. Получение удаленных изменений
git clone — создает «клон» удаленного хранилища.
git remote add — добавляет удаленный репозиторий с указанным URL-адресом соединения.
git fetch — извлекает изменения в ветке удаленного отслеживания для удаленного репозитория.
git pull — выборки с последующим слиянием.
git push — передает изменение из локальной ветви через удаленную ветвь отслеживания в удаленное хранилище.
На Фигуре 12 показан git fetch
; обновляет ветку удаленного отслеживания.Затем вы просто выполняете обычную операцию слияния между удаленной ветвью отслеживания и локальной ветвью, в этом примере git checkout master; git merge repo1 / master
. После выборки вы можете использовать имя FETCH_HEAD
в команде слияния в качестве ярлыка для извлеченной удаленной ветви, например, git merge FETCH_HEAD
. Кроме того, аналогично обсуждению выше, это объединение может привести к ускоренному слиянию, слиянию без конфликтов или конфликту, который необходимо разрешить вручную.
Команда git pull
— это удобная команда, которая объединяет выборок
с слиянием
.
После внесения изменений в локальный филиал их необходимо перенести в удаленный филиал. Это делается с помощью команды push
, которая передает локальные изменения в удаленную ветвь. Это противоположность для получения
, а не противоположность для
. Однако он делает больше, чем просто выборку, потому что обновляет локальную копию удаленной ветви, а также удаленную ветку в другом хранилище, как показано на рисунке 13. push
также позволяет создавать новые ветви в удаленной репозиторий.
Рисунок 13. Нажатие на изменение
Есть одна защита. Это происходит успешно, а в противном случае прерывается, когда отправка приведет к ускоренному слиянию в удаленной ветви в удаленном хранилище. Если это не так, то в удаленной ветви уже есть некоторые другие изменения (коммиты) из других репозиториев или коммиттеров. Git прерывает пуш и оставляет все как есть. Затем вам нужно получить изменения, объединить их с вашей локальной веткой и попробовать еще раз.
Обратите внимание, что в таких случаях вы можете выполнить обычное слияние, но также есть возможность выполнить слияние rebase, чтобы перебазировать изменения в вашей локальной ветке в новый, обновленный заголовок удаленной ветки.
Помимо команд fetch и push есть еще один способ распространения патчей; старый стиль, по почте. Для этого есть команда git format-patch
, которая создает файл исправлений для каждого коммита, который ведет от данного коммита к состоянию текущей ветви. git am
применяет эти файлы исправлений к текущей ветке.
Предостережения
Одно предупреждение: если вы попытаетесь вставить хранилище, где кто-то фактически отслеживает ветку и работает над ней локально.Это, вероятно, испортит управление филиалом, поэтому Git предупредит вас об этом и попросит сначала синхронизировать состояние удаленной ветви с pull
.
Также становится ясно, что вы не должны перебазировать ветку удаленного отслеживания. Это больше не будет соответствовать удаленной ветви, таким образом, это не даст быстрого слияния на push
. Вы нарушили свою структуру хранилища.
Advanced Git
Рисунок 14. Пример структуры с несколькими хранилищами
Обычно, даже с Git, существует структура типа star , в которой есть один центральный репозиторий, который служит в качестве основного, и локальные репозитории для каждого пользователя.Но это не обязательно так. Вы можете добавить соединения с удаленным репозиторием, как в сети, например, с перекрестными соединениями, как показано на рисунке 14.
Выше я описал перебазирование как воспроизведение наборов изменений поверх другой точки ветвления (или отклонения) от исходной ветки. Git обычно выполняет воспроизведение в том порядке, в котором были сделаны коммиты. В качестве расширенной функции git rebase -i
позволяет вам фактически выбирать, какие коммиты следует делать в каком порядке, и даже если коммиты могут быть удалены или два коммита могут быть объединены («сдавлены»).Просто убедитесь, что вы не делаете это с коммитами, которые уже были выдвинуты — в противном случае те, которые работают на основе этих коммитов, могут получить много конфликтов.
Я также написал, как проверить конкретную ветку, но вы также можете проверить любой коммит (снимок). Это позволяет указателю HEAD указывать на коммит, а не на ветвь. Это называется режим отсоединенного HEAD . Когда вы фиксируете изменение в этой ситуации, вы начинаете новый поток развития. В основном вы разветвляетесь, но не указав название этой новой ветви.Совет разработки доступен только при использовании идентификатора фиксации; это не достижимо никаким refname. Вы можете создать ветку из этого HEAD, используя обычную команду « git branch
».
Что происходит с коммитами, которые недоступны по какой-либо ссылке? Ну, если вы не делаете ничего особенного, они хранятся в хранилище. Тем не менее, вы можете и службы хостинга могут фактически запустить Git GC
, сборщик мусора Git для удаления ненужных файлов.Коммиты, которые не доступны ни по одному имени рефлекса, не нужны и поэтому будут удалены. Поэтому рекомендуется всегда работать с реальной веткой, особенно когда в Git так быстро и легко создать новую ветку.
Заключение
Git с одной стороны основывается на простых принципах, но гибкость, которую он обеспечивает, иногда может быть подавляющей. Главное, что Git управляет снимками и наборами изменений между снимками. Наиболее распространенные команды применяются и откатывать эти наборы изменений между различными ветвями.Второй вывод заключается в том, что обработка удаленной ветви в основном такая же, как и обработка локальной ветви, потому что даже есть локальное зеркало удаленной ветви.
На этом я закончил свою скоростную пробежку по работе Git. Эти команды охватывают в основном все, что я делаю с Git. Более подробную информацию обо всех командах можно найти на соответствующих страницах руководства, и благодаря знаниям, приведенным здесь, вы, надеюсь, сможете лучше понять их и использовать их. Кроме того, сами команды и git status
часто дают ценные советы о том, что делать дальше.
Еще одним отличным инструментом, который поможет вам понять Git, является графический инструмент gitk , который показывает структуру локального репозитория. Используйте gitk --all
, чтобы показать все ветви и теги и т. Д. Он также предоставляет простой интерфейс для запуска действий в Git.
Git обычно уже установлен в вашей системе Linux. Возможно, вам придется установить инструменты разработки из вашего менеджера пакетов. Для Windows вы можете скачать его на домашней странице Git.
Я надеюсь, что теперь вы лучше понимаете работу Git и не боитесь использовать его гибкость.
Спасибо за некоторые интересные дискуссии на эту тему и за рецензирование этой статьи, перейдите к моему коллеге Витольду Щепонику, который понимает Git даже лучше, чем я.
Git · GitHub
перейти к содержанию Зарегистрироваться- Почему GitHub?
Особенности →
- Обзор кода
- Управление проектами
- Интеграция
- Действия
- Пакеты
- Безопасность
- Управление командой
- Хостинг
- Мобильный
- Отзывы клиентов →
- Безопасность →
- команда
- предприятие
- Проводить исследования
- Исследуйте GitHub →
учиться и внести свой вклад
- Темы
- Коллекции
- Тенденции
- Learning Lab
- Руководства с открытым исходным кодом
Общайтесь с другими
- События
- Общественный форум
Использование Git — GitHub Docs
GitHub Docs- Все продукты
- GitHub.com
- Начиная
- Быстрый старт
- Настроить Git
- Создать репо
- Вилка репо
- Быть социальным
- Узнав о GitHub
- Продукты GitHub
- Изучение ранних версий доступа с предварительным просмотром функций
- Типы учетных записей GitHub
- FAQ об изменениях в планах GitHub
- GitHub CLI
- GitHub Desktop
- GitHub для мобильных
- Права доступа на GitHub
- GitHub глоссарий
- Git шпаргалка
- Git и GitHub учебные ресурсы
- Регистрация на GitHub
- Регистрация новой учетной записи GitHub
- Подтверждение вашего адреса электронной почты
- Настройка пробной версии GitHub Enterprise Cloud
- Настройка пробной версии GitHub Enterprise Server
- Изучение проектов на GitHub
- Поиск способов внести свой вклад в открытый исходный код на GitHub
- Сохранение репозиториев со звездами
- Следующие люди
- Использование GitHub
- Поддерживаемые браузеры
- Устранение проблем с подключением
- Горячие клавиши
- Быстрый старт
- Учетные записи пользователей
- Управление настройками учетной записи пользователя
- О вашей личной панели
- Изменение вашего имени пользователя на GitHub
- Слияние нескольких учетных записей пользователей
- Преобразование пользователя в организацию
- Удаление вашей учетной записи
- Уровни разрешений для хранилища учетных записей пользователей
- Уровни разрешений для пользовательских плат проектов
- Управление настройками безопасности и анализа для вашей учетной записи пользователя
- Управление доступом к доскам проектов вашей учетной записи
- Лучшие практики для ухода из вашей компании
- Что делает флажок «Доступно для проката»?
- Управление настройками электронной почты
- Управление настройками учетной записи пользователя
github — Как на самом деле работает git fork?
Переполнение стека- Товары
- Клиенты
- Случаи использования
- Переполнение стека Публичные вопросы и ответы
- Команды Частные вопросы и ответы для вашей команды
- предприятие Частные вопросы и ответы для вашего предприятия
- работы Программирование и связанные с ним технические возможности карьерного роста
- Талант Нанимать технический талант
- реклама Связаться с разработчиками по всему миру