Продолжаю увлекательное знакомство новичка с сервисом GitHub и с системой контроля версий Git.
Так как имею учетную запись на GitHub, которую регулярно использую, то у меня возник вопрос, который не мог не возникнуть, рано или поздно. Касается он такой темы, как fork.
Не знаю даже, как правильно поступить дальше - попытаться самому описать вопрос, своими словами; или же попытаться сделать вольный перевод статьи на эту тему - Fork A Repo. Но лучше все же расскажу своими словами.
Fork - это копия репозитория
Fork - это вcего навсего копия репозитория. Это тоже самое, что branch в Git. Только на GitHub такой branch называется fork - присутствует своя терминология. Само слово fork в переводе означает ответвление. Для того, чтобы воспользоваться fork, нужно иметь свою собственную учетную запись на GitHub; и нужно войти под ней на GitHub в момент выполнения fork.
Для чего нужен fork? Для тех же целей, что и branch в Git. С помощью него создается точная копия оригинального репозитория, только на сервисе GitHub. В копии репозитория можно вносить свои собственные изменения, редактировать файлы или удалять директории.
Как только все изменения будут внесены, то можно поделиться ими - отправить авторам оригинального репозитория запрос на слияние вашего измененного репозитория с их оригинальным репозиторием. Такой запрос называется pull request.
Если авторам оригинального репозитория ваши изменения понравятся, то они могут внести их в свой собственый оригинальный репозиторий - принять запрос и выполнить слияние.
Существование fork полностью отвечает идеологии OpenSource и GitHub, в частности. Идеология OpenSource заключается в свободном обмене исходным кодом программ и fork однозначно помогает в этом деле. С помощью fork можно одним движением получить копию любого исходного кода, выложенного на GitHub в свободном доступе.
Fork - создание копии репозитория
Давайте от слов перейдем к делу и на практике выполним хотя бы один fork на GitHub. К слову сказать, в приведенной выше статье-оригинале Fork A Repo дается ссылка на репозиторий Spoon-Knife, созданный авторами статьи для учебных целей - научиться работать с fork на GitHub. Вы, уважаемый читатель, также можете свободно воспользоваться им для себя, чтобы научиться пользоваться fork.
Я воспользуюсь другим репозиторием, который выложен в свободном доступе достаточно известным верстальщиком Юрием Артюхом (akella). Ниже привожу шаги по созданию Fork на GitHub.
захожу на GitHub под своей учетной записью
перехожу по ссылке github/akella/sass, по которой расположен репозиторий akella/sass
Фактически, теперь я нахожусь в репозитории akella/sass пользователя akella (Юрий Артюх). Об этом красноречиво говорит надпись akella/sass в левом верхнем углу окна браузера. В правом верхнем углу окна браузера нахожу кнопку Fork.
И нажимаю на нее:
Может случиться, что вы, уважаемый читатель, ничего и не заметите. Но это не так на самом деле. Приглядитесь к “главной” надписи - она изменилась с akella/sass на gearmobile/sass; а ниже мелким шрифтом еще - forked from akella/sass. Думаю, тут и говорить больше нечего - все и так понятно.
Теперь этот репозиторий мой - точнее, у меня теперь копия оригинального репозитория akella/sass. Я могу делать с ним все, что мне понадобиться - просто пользоваться или же вносить свои собственные изменения.
Если изменения мне покажутся существенными, то я могу отправить пользователю akella запрос на слияние pull request моего репозитория gearmobile/sass с его репозиторием akella/sass. Если пользователь akella посчитает эти изменения действительно существенными (с его точки зрения), то он может и принять мой запрос.
Я также могу удалить репозиторий gearmobile/sass, если в нем отпадет надобность. Надеюсь, вы хорошо помните, как удалять репозиторий на GitHub - “Как удалить репозиторий на GitHub”.
Продолжаю совместно с вами постепенно изучать магию Git\GitHub.
Слово магия здесь применено не случайно - не иначе, как магией возможности Git\GitHub не назовешь. По крайней мере, я впечатлен этими возможностями. Другое дело, что процесс изучения Git у меня лично идет как-то тяжеловато. Ну, это не страшно - главное, не останавливаться!
В этом разделе я попытаюсь осветить для себя (и возможно, для вас, уважаемый читатель) вопрос создания ветвей (branches) в Git, перемещение между ветвями (branches), слияние (merge) ветвей. Этот вопрос очень подробно и хорошо описан на странице официальной документации - “Git Branching - Basic Branching and Merging”. Здесь я попробую самостоятельно описать данный вопрос.
Инициализация Git-репозитория
Создаю тестовую директорию git_branches, в которой будут производиться эксперименты по созданию ветвей в Git. Внутри этой директории создаю два файла - индексный файл и файл таблиц стилей. А затем инициализирую Git-репозиторий, добавляю созданные файлы под версионный контроль Git:
Обратите на строку On branch master в выводе команды git status. Это не пустой набор служебной информации - здесь говориться о том, что в ветви master нечего фиксировать и рабочая директория чистая.
Итак, мы уже кое-что узнали. А именно - при инициализации Git-репозитория была автоматически создана ветвь (branch) по имени master. И на данный момент мы находимся в этой ветви.
Конечно, на самом деле это пока мало о чем говорит, так как не с чем сравнивать. Поэтому давайте я немного отредактирую оба файла index.html и style.css, проиндексирую\зафиксирую их.
В браузере примерный вид странички будет выглядеть таким образом:
Git - создание новой ветви (branch)
В системе Git (как уже упоминалось ранее) имеется механизм ветвления (branches). Попробую на словах объяснить, что он из себя представляет.
Допустим, в моем текущем проекте, у которого имеются два файла, нужно внести кардинальные изменения. Причем, изменения такого рода, что они могут нарушить работу уже существующего проекта. Чтобы обезопасить себя (подстраховать), создаю точную копию существующего проекта и перехожу в нее для дальнейшей работы.
Давайте я на практике осуществлю вышесказанные действия. Для этого создаю новую ветвь с произвольным именем second, которая на этом этапе будет точной копией ветви master:
$gitcheckout-bsecondSwitchedtoanewbranch'second'
Строка Switched to a new branch ‘second’ услужливо информирует, что меня автоматически “перебросило” во вновь ветвь second. Можно проверить себя, набрав в консоли:
Отлично! Теперь давайте я внесу некоторые изменения в файлы index.html и style.css и мы вместе посмотрим на результат в окне браузера. Изменения будут касаться добавления блока-обертки, еще нескольких параграфов и другой легкой стилизации.
Не забуду также проиндексировать и зафиксировать внесенные изменения. Обратите внимание на вид команды - git commit -a. Эта команда является сокращенным вариантом двух команд: git add и git commit -m. Применяется, когда нужно “проскочить” этап индексирования и сразу зафиксировать изменения.
Смотрим, что у нас получилось в окне браузера - то, что и ожидалось:
Git - переключение между ветвями (branches)
А теперь настал самый интересный момент. Как вы помните, мы сейчас находимся в ветви second. Давайте я переключусь в ветвь master и мы снова посмотрим в окно браузера:
$gitcheckoutmasterSwitchedtobranch'master'
Оп! Мы видим старую картину - Git “запечатлел” тот момент, когда мы совершили переход из ветви master в ветвь second. Другими словами, мы вернулись в последнее зафиксированное состояние ветви master:
Мне кажется, уже сейчас должно быть понятно, что такое ветви (branches) в Git и для чего они предназначены. На самом деле это действительно очень просто.
Git - слияние ветвей (branches)
В предыдущем шаге я создал ветвь second, в которую внес “рискованные” изменения, чтобы проверить, “оправдают” ли они себя. Изменениями я доволен и хотел бы добавить их в первоначальную ветку master, чтобы потом продолжить развитие проекта уже с этого места.
Фактически, я хочу сделать слияние двух веток - master и second. Это сделать очень просто - для этого я перехожу в ветку master. То есть, я должен находиться в той ветке, в которую я вношу изменения из другой ветки. А затем произвожу само слияние:
Команда слияния проста - я просто указываю имя той ветки (branch), которую хочу слить (merge) с текущей, в которой я нахожусь на данный момент.
При слиянии ветвей зачастую может возникнуть ситуация, когда происходит конфликт между двумя ветвями. Рассмотрение вопроса решения конфликтов при слиянии не рассматривается мною, так как на данный момент еще не освоил этот вопрос до конца.
Давайте снова “заглянем” в окно браузера - что он нам интересного покажет?
Показал он то, что и следовало показать - результат объединения двух ветвей master и second.
Git - графическое представление ветвей (branches)
Система Git имеет в своем составе возможность графического представления ветвления в репозитории. Причем, такое представление можно сделать даже в консоли, с помощью псевдографики.
Это можно сделать, набрав в консоли команду:
$gitlog--oneline--abbrev-commit--all--graph
На Stack Overflow я нашел примеры красивых изображений консоли с псевдографическим выводом команды git log:
На самом деле вариантов использования команды git log с ключом –graph бесчисленное множество. Поэтому нужно выбирать именно то, что нужно и нравиться именно вам.
Помимо псевдографики, ветви в Git можно визуализировать с помощью настоящего графического приложения. Под Mac OS X и Linux имеется достаточно большое количество таких приложений. Например, под Mac OS X это GitX, под Linux - Gitk или Gitg:
Git - удаление ветви (branch)
В разделе слияния ветвей в Git я научился процессу объединения двух ветвей в одну. Такой процесс в Git имеет название merge (слияние). Теперь ветвь master имеет в себе все, что есть и в ветви second. Поэтому ветвь second можно удалить.
Еще один важный практический вопрос при работе с Git - это операции с файлами.
В частности, это операции удаления и переименования файлов. В системе Git имеются специальные команды, которые очень похожи на консольные команды rm и mv в Linux/Mac OS. Но для Git они выглядят несколько иначе: git rm - для удаления файлов и git mv - для переименования файлов. Ниже я рассмотрю обе эти комадны более подробно.
Команда git rm
Для удаления файлов в системе Git, как уже упоминалось выше, имеется специальная команда git rm. Ее отличие от обычной консольной команды rm (в том же Linux) заключается в особенности самой системы Git.
Как хорошо известно, в системе Git файл может одновременно существовать в трех ипостасях: в области “Working Directory”, в области “Staging Area”, в области “Repository”. Удаление файла из области “Working Directory” не приведет к его удалению из областей “Staging Area” и “Repository”.
Поэтому, чтобы удалить файл, нужно (в идеале) выполнить три команды подряд для удаления файла из Рабочей области “Working Directory”, затем из области индекса “Staging Area” и потом из области репозитория “Repository”:
Команда git rm является ни чем иным, как “вшитым” в Git сокращением двух первых команд:
$rmindex.html$gitadd.
Сделано это всего лишь для удобства пользования системой Git. Давайте на примере посмотрим работу команды git rm. Предположим, что имеется файл index.html, который проиндексирован и зафиксирован.
Удалим его командой git rm:
Видим, что файл index.html был сразу удален из двух областей: рабочего каталога “Working Directory” и области индексации “Staging Area”. Но в репозитории файл все же остался, о чем говорит вывод команды git status.
Любой последующий commit зафиксирует удаление этого файла:
Команда git rm -cached
У команды git rm имеется пара полезных ключей, одним из которых является ключ –cached. Задача этого ключа - позволить команде git rm удалить файл из области индексирования “Staging Area”, но при этом оставить его в области рабочего проекта “Working Directory”. Давайте рассмотрим пример, когда создан файл second.html и произведена его индексация (но не фиксация):
Удалим его командой git rm –cached:
Отлично! Видим, что произошло удаление файла second.html. Кроме того, команда git status показывает, что в рабочей области “Working Directory” имеется неотслеживаемый (untracked) файл по имени second.html.
Команда git rm -f
В предыдущем разделе я рассмотрел вариант, когда созданный и проиндексированный файл удаляется из области индексирования “Staging Area”, но остается в области “Working Directory”. Выполняется это с помощью команды git rm –cached.
Логическим продолжением этой команды является та же самая команда git rm, но с ключом -f - git rm -f. Такая команда удаляет проиндексированный (но еще не зафиксированный) файл как из области “Staging Area”, так и из области “Working Directory”.
Давайте рассмотрим на примере созданного и проиндексированного файла third.html его удаление с помощью команды git rm -f:
Файл third.html удален как из области “Staging Area”, так и из области “Working Directory”. В итоге можно сказать, что между командой git rm -f и командой git rm практически нет никакой разницы.
Команда git mv - перемещение или переименование файлов
В системе Git имеется “своя” команда для перемещения или переименования файлов. Слово “своя” здесь не даром взято в кавычки - аналогия с командой git rm полная. Команда git mv перемещает или переименовывает файлы, автоматически “уведомляя” об этих событиях область “Staging Area”:
Остается только зафиксировать эти изменения любым коммитом:
$gitcommit-m'Move index.html to papka'[master868d428]Moveindex.htmltopapka1filechanged,0insertions(+),0deletions(-)renameindex.html=>papka/index.html(100%)
Переименуем файл index.html с помощью команды git mv:
Вот и все несложные операции по перемещению\переименованию или удалению файлов с помощью команд git rm и git mv, под всевидящим оком Git.
Продолжаю открывать для себя возможности системы Git и сервиса GitHub.
Уже сейчас, обладая минимальными базовыми знаниями Git и владея учетной записью на сервере GitHub, я не представляю, как я мог жить раньше без обоих этих вещей. Это действительно удобно и надежно!
Благодаря им я знаю, что у меня никогда и ничто не потеряется; и все, что нужно - у меня всегда под рукой. На работе поработал над чем-либо - отправил на GitHub; домой пришел - “стянул” наработки с GitHub и продолжил работу с прерванного места.
Вот на последнем я хотел бы остановиться подробнее. Конечно, веб-разработчик, давно и хорошо знакомый с Git и GitHub, может только улыбнуться насчет того, чем я собираюсь поделиться. Настолько все это просто и понятно. Но это просто и понятно для него, опытного web-разработчика. А для начинающего веб-программиста - это новое и неизведанное. Впрочем, достаточно лирики - переходим к практике.
GitHub - команда push
В предыдущей статье я познакомился с возможностью создания репозитория на сервисе GitHub. И возможностью клонирования этого репозитория на локальную машину - “GitHub и Git - создание и работа с репозиторием”.
Напомню, что в том примере было произведено клонирование репозитория с помощью команды:
$gitclonegit@github.com:gearmobile/arbeit.git
Другими словами, было произведено копирование существующего репозитория с удаленного сервера на локальную машину. Причем, копирование как есть - полностью весь репозиторий, со всеми его файлами, коммитами, индексами и тому подобным.
После внесений изменений в локальный репозиторий - индексации и фиксации - необходимо было отправить произведенные изменения на удаленный сервер, на GitHub.
Для этой цели существует (и я ею воспользовался) команда push (отправить). К примеру, давайте я внесу еще кое-какие изменения в локальном репозитории, затем проиндексирую и зафиксирую их, а затем отправлю на GitHub:
$gitadd.$gitcommit-m'Continue write article about push and pull in GitHub'[master5af3abc]ContinuewritearticleaboutpushandpullinGitHub1filechanged,18insertions(+)$gitstatusOnbranchmasterYourbranchisaheadof'origin/master'by1commit.(use"git push"topublishyourlocalcommits)nothingtocommit,workingdirectoryclean$gitpush...Countingobjects:7,done.Deltacompressionusingupto4threads.Compressingobjects:100%(4/4),done.Writingobjects:100%(4/4),1.65KiB|0bytes/s,done.Total4(delta1),reused0(delta0)Togit@github.com:semenencko/articles022b756..5af3abcmaster->master
Вот - все наработки, которые я сделал на домашнем компьютере, оказались с считанные секунды помещенными на сервере GitHub, под бдительным оком Git.
GitHub - команда pull
Продолжим логическую картину моего рабочего процесса (workflow). На следующий день я прихожу на работу и у меня есть время и возможность поработать над своим проектом. Естественно, я хочу продолжить с того места, на котором остановился дома. Для этого я воспользуюсь командой pull, чтобы “стянуть” с GitHub последние изменения.
В данном случае команда pull будет выглядеть так:
В выводе консоли (на картинке) видно, что было произведено добавление одного измененного файла по имени README.md, в котором были добавлены две строки.
Обратите внимание на разницу между командами clone и pull в данном случае. Команда clone копирует весь репозиторий целиком, как есть - со всеми его файлами. Команда pull копирует разницу между удаленным и локальным репозиторием. Эту разницу можно назвать дельта или patch.
В результате вышеприведенной команды в считанные секунды я получаю на рабочем компьютере точную копию того проекта, над которым работал дома. И могу продолжать с того места, на котором остановился.
GitHub - команда fetch
Существует разновидность команды pull - это команда fetch. И одна, и вторая команда выполняют одинаковые задачи - получение patch удаленного репозитория. Но делают они это по разному.
Команда pull получает patch репозитория и автоматически производит слияние удаленной и локальной ветвей репозитория. Если произойдет конфликт слияния, то только в этом случае слияния не произойдет и решать конфликт придется вручную.
Команда fetch также производит получение patch удаленного репозитория. Но при этом автоматического слияния ветвей удаленного и локального репозиториев не происходит:
На картинке выше показано, что была выполнена команда git fetch после того, как на стороне сервиса GitHub было произведено редактирование файла README.md. Однако, последующая команда git status показала, что изменения есть, но они не слиты с локальной ветвью репозитория. И порекомендовала выполнить команду git pull, чтобы произвести такое слияние.
Помимо этого, имеются изменения в локальном репозитории, которые не проиндексированы и не зафиксированы. Что же, исправляю ситуацию - последовательно ввожу команды:
Производить слияние и разрешение конфликтов при слиянии я еще не умею, поэтому вопрос, как произвести слияние ветвей после команды git fetch я опущу в данной статье.
Вернувшись к вышесказанному, можно сделать вывод, что команда pull более универсальная, нежели команда fetch. Именно команду pull имеет смысл применять в практической работе.
Как новичок в работе с системой GitHub, столкнулся с вопросом - как удалить созданный на GitHub репозиторий?
Оказалось, что ничего сложного в этом нет. Однако, задача эта и не такая простая, как может показаться. По крайней мере, чисто интуитивно у меня не получилось ее выполнить - пришлось искать ответ в Сети.
Итак, у меня есть учетная запись на GitHub, под которой создана пара репозиториев. Один из этих репозиториев был создан в учебных целях, поэтому для моей дальнейшей работы он мне не пригодиться и его можно удалить.
Список репозиториев на GitHub
Для начала открою свою страничку на GitHub и посмотрю, какие репозитории у меня уже есть:
Один из репозиторев - arbeit - можно удалить.
Для этой цели нужно просто зайти в него по ссылке:
В правом нижнем углу окна браузера, в списке, имеется строка Settings. Открываем ее, сразу же копируем имя репозитория в поле Repository name (оно нам понадобиться еще здесь) и прокручиваем страницу вниз, пока не находим раздел с устрашающим названием Danger Zone. В этой опасной зоне находим подраздел Delete this repository с одноименной кнопкой Delete this repository.
Жмем на эту кнопку и получаем в результате окно с предупреждением об удаленни репозитория. В окне запроса имени удаляемого репозитория вводим (или вставляем из буфера обмена) - arbeit:
Снова жму на кнопку, на этот раз с еще более страшным напоминанием о последствиях совершаемого мною шага. И все! Репозиторий arbeit удален:
Ничего сложного, но так сразу и не догадаешься, что нужно делать. Разработчики GitHub постарались и обезопасили пользователей от случайного удаления репозиториев с данными.