Введение¶
Git (произн. «гит») — распределённая система управления версиями файлов. Проект был создан Линусом Торвальдсом для управления разработкой ядра Linux. На сегодняшний день поддерживается Джунио Хамано.
Система спроектирована как набор программ, специально разработанных с учётом их использования в скриптах. Это позволяет удобно создавать специализированные системы контроля версий на базе Git или пользовательские интерфейсы. Например, Cogito является именно таким примером фронтенда к репозиториям Git, а StGit использует Git для управления коллекцией патчей.
Git поддерживает быстрое разделение и слияние версий, включает инструменты для визуализации и навигации по нелинейной истории разработки. Как и Darcs, BitKeeper, Mercurial, SVK, Bazaar и Monotone, Git предоставляет каждому разработчику локальную копию всей истории разработки; изменения копируются из одного репозитория в другой.
Удалённый доступ к репозиториям Git обеспечивается git-daemon, gitosis, SSH- или HTTP-сервером. TCP-сервис git-daemon входит в дистрибутив Git и является наряду с SSH наиболее распространённым и надёжным методом доступа. Метод доступа по HTTP, несмотря на ряд ограничений, очень популярен в контролируемых сетях, потому что позволяет использовать существующие конфигурации сетевых фильтров.
Объяснил, объяснил
«Удаленный» для ветви — это URL-адрес, с которого вы репо получает изменения. Ваш местный Репо полностью принадлежит вам — на него не влияет код других людей, пока они не передадут свои коммиты на удаленный компьютер. Надеюсь, вы все используете один и тот же пульт, и все синхронизируется, но этот пульт является лишь конечной точкой. Вы можете клонировать эту конечную точку и переключиться на новый пульт без особых проблем.
Всякий раз, когда вы клонируете новый репозиторий, пульт по умолчанию устанавливается как «источник». Вы можете найти пульты для любой данной репо, запустив:
git remote -v
Это, вероятно, отобразит URL вашего основного репозитория на GitHub или любом другом сервисе, который вы используете. Если у вас есть несколько пультов, они тоже появятся здесь.
Но только потому, что это пульт по умолчанию, это не значит, что вы ограничены одним. Зачем вам два пульта? Что ж, хороший пример использования AWS CodeCommit, Это хостинг репозиторий, и имеет множество интеграций со своей вычислительной платформой EC2, что позволяет автоматизировать развертывание кода на ваших серверах непосредственно из системы контроля версий.
Тем не менее, CodeCommit довольно неуклюжий по сравнению с более сфокусированным провайдеры, такие как GitHub, GitLab и BitBucket, и не имеют таких интеграций CI / CD, которые делают этих провайдеров великими. Таким образом, вы застряли с дилеммой — используйте CodeCommit по умолчанию решение или создайте свой автоматический конвейер развертывания кода самостоятельно.
Однако, с несколькими пультами, вы можете легко отправить код во второй репозиторий. Всякий раз, когда вы хотите обновить свои серверы, вы можете перенести изменения из вашего основного управления исходным кодом в CodeCommit, чтобы запустить конвейер развертывания.
Удаление и переименование удалённых репозиториев
Для переименования удалённого репозитория можно выполнить . Например, если вы хотите переименовать в , вы можете это сделать при помощи :
Стоит упомянуть, что это также изменит имена удалённых веток в вашем репозитории. То, к чему вы обращались как , теперь стало .
Если по какой-то причине вы хотите удалить удаленный репозиторий (вы сменили сервер или больше не используете определённое зеркало, или кто-то перестал вносить изменения), можете использовать или :
При удалении ссылки на удалённый репозиторий все отслеживаемые ветки и настройки, связанные с этим репозиторием, так же будут удалены.
Branch
git checkout -b <branch-name>
Alternatives:
git branch <branch-name> && git checkout <branch-name>
git branch -m <new-branch-name>
Alternatives:
git branch -m <new-branch-name>
git push origin --delete <remote-branch-name>
Alternatives:
git push origin :<remote-branch-name>
Удалить ветки, которые уже слиты с master
git branch --merged master | grep -v '^\*' | xargs -n 1 git branch -d
Alternatives:
git branch --merged master | grep -v '^\*\| master' | xargs -n 1 git branch -d # will not delete master if master is not checked out
git branch -a --contains <commit-ish>
Alternatives:
git branch --contains <commit-ish>
Вы хотите заставить толкнуть
Что вы в основном хотите сделать, так это принудительно нажать локальную ветвь, чтобы перезаписать удаленную.
Если вам нужно более подробное объяснение каждой из следующих команд, см. Раздел «Мои подробности» ниже. В основном у вас есть 4 разных варианта принудительного нажатия с помощью Git:
Если вы хотите более подробное объяснение каждой команды, посмотрите раздел с моими длинными ответами ниже.
Предупреждение: принудительное нажатие перезапишет удаленную ветку с состоянием ветки, которую вы нажимаете. Убедитесь, что это именно то, что вы действительно хотите сделать, прежде чем использовать его, иначе вы можете перезаписать коммиты, которые действительно хотите сохранить.
Вы хотите заставить толкнуть
То, что вы в основном хотите сделать, — это принудительно нажать вашу локальную ветвь, чтобы перезаписать удаленную.
Если вы хотите получить более подробное объяснение каждой из следующих команд, обратитесь к разделу мои сведения ниже. В основном у вас есть 4 различных варианта силового толчка с помощью Git:
Если вы хотите получить более подробное объяснение каждой команды, то смотрите раздел мои длинные ответы ниже.
Предупреждение: принудительное нажатие перезапишет удаленную ветвь с состоянием ветви, которую вы нажимаете. Убедитесь, что это то, что вы действительно хотите сделать, прежде чем использовать его, иначе вы можете перезаписать коммиты, которые на самом деле хотите сохранить.
Опуская ветку
Когда ветку нажимаем ветку опущен, Git будет вычислять его вне зависимости от настроек конфигурации. В версиях Git после 2.0 новое РЕПО будет иметь настройки по умолчанию для выталкивания текущей извлеченной ветви:
в то время как до 2.0 новые РЕПО будут иметь настройки по умолчанию для запуска нескольких локальных ветвей. Речь идет о настройках и (см. ниже).
Опуская пульт и ветку
Когда и пульт дистанционного управления, и ветвь опущены, поведение just определяется вашими настройками Git config:
-
Начиная с Git 2.0, настройка по умолчанию, , в основном просто подтолкнет вашу текущую ветвь к ее восходящей удаленной встречной части. Пульт дистанционного управления определяется параметром ветви, а в противном случае по умолчанию используется исходное РЕПО.
-
До Git версии 2.0 настройка по умолчанию, , в основном просто перемещает все ваши локальные ветви в ветви с одинаковым именем на удаленном компьютере (который по умолчанию имеет значение origin).
Вы можете прочитать больше настроек , прочитав или онлайн-версию страницы руководства git-config(1).
Сила толкает более безопасно с
Принудительное нажатие с помощью «lease» позволяет принудительному нажатию потерпеть неудачу, если на пульте есть новые коммиты, которые вы не ожидали (технически, если вы еще не загрузили их в свою ветвь удаленного отслеживания), что полезно, если вы не хотите случайно перезаписать чужие коммиты, о которых вы еще даже не знали, и вы просто хотите перезаписать свои собственные.:
Вы можете узнать более подробную информацию о том, как использовать , прочитав любое из следующих действий:
-
документация
- Git: как игнорировать быструю перемотку вперед и вернуть origin к более ранней фиксации(коммита)?
Как перенести изменения из локального репозитория в удаленный репозиторий в Git
Чтобы протолкнуть некоторые изменения в удаленный репозиторий, этот репозиторий должен, прежде всего, содержать некоторые коммиты в локальной системе. Поэтому в этом разделе мы сначала создадим некоторые изменения в репозитории. Во-вторых, мы зафиксируем эти изменения и, наконец, отразим их в удаленном репозитории.
Перед созданием изменений в репозитории убедитесь, что вы выполнили следующие операции:
- У вас раздвоенный репозитория на GitHub.
- Вы клонировали один и тот же репозиторий на локальную машину.
В качестве хорошей практики сначала проверьте, что у вас есть чистый репозиторий с помощью команды git status (никаких ожидающих изменений для фиксации).
После выполнения команды git status появятся следующие строки:
On branch master: означает, что в данный момент мы находимся в главной ветви. Поскольку других ветвей пока нет, мы по умолчанию находимся в главной ветви.
Your branch is up to date with origin/master: Origin — это имя удаленного репозитория, которое мы дали при подключении локального репозитория к удаленному репозиторию.
Последовательность действий
- Перечислите все файлы с командой ls в репозитории.
Так как существует только один файл (README.md это всего лишь инструкция), давайте внесем некоторые изменения в его содержание.
- Откройте файл с помощью вашего любимого редактора и внесите в него любые изменения.
- Мы изменили файл на следующий код.
- Добавьте внесенные изменения в промежуточную область и зафиксируйте их.
Примечание: GitHub и Git распознают любые изменения только через коммиты (commits). Если пользователь не зафиксировал изменения и пытается протолкнуть их на GitHub, он отобразит сообщение “Everything is up-to-date”
- Введите следующую команду, чтобы перенести эти изменения в репозиторий GitHub, и нажмите клавишу enter.
- Пользователь получает приглашение предоставить учетные данные с помощью GitHub в качестве части безопасности. Введите свои учетные данные и нажмите на кнопку входа в систему.
- Как только пользователь получит одобрение и изменения объединятся, он получит следующее сообщение в Git Bash.
Примечание: последние две строки выглядят следующим образом:
https://github.com/harishrajora805/ToolsQA.git: URL-адрес репозитория, который отражает изменения.
1в4522а..285f559: показывает хэш-значение обеих ветвей. Таким образом, хэш-значение конечного коммита, отраженного на GitHub, равно 285f559.
master -> master: строка master — > master показывает исходную ветвь, из которой происходит слияние с целевой ветвью. В приведенном выше сценарии обе ветви являются главными.
Строка Writing Objects: 100% имеет важное значение. В Git можно сказать, была ли команда push выполнена успешно или нет, только взглянув на эту строку
Если она показывает 100%, то все изменения успешно перенесены в облако.
Наряду с простой и понятной командой, которую мы обсуждали выше, как и любую другую команду в Git, мы можем использовать параметры при выполнении команды для достижения конкретной задачи. Например, если вы хотите протолкнуть все ветви, вы будете использовать опцию all и так далее. Давайте рассмотрим некоторые из вариантов в Git.
Добавление удалённых репозиториев
В предыдущих разделах мы уже упоминали и приводили примеры добавления удалённых репозиториев, сейчас рассмотрим эту операцию подробнее. Для того, чтобы добавить удалённый репозиторий и присвоить ему имя (shortname), просто выполните команду :
Теперь, вместо указания полного пути, вы можете использовать . Например, если вы хотите получить изменения, которые есть у Пола, но нету у вас, вы можете выполнить команду :
Ветка из репозитория Пола сейчас доступна вам под именем r. Вы можете слить её с одной из ваших веток или переключить на неё локальную ветку, чтобы просмотреть ее содержимое. Более подробно работа с ветками рассмотрена в главе «Ветвление в Git».
Git push
Команда в ходе выполнения переносит все изменения, внесенные юзером, в удаленный репозиторий (например, такой как GitHub):
Git push 'remote_name' 'branch_name'
Чтобы отправить данные в удаленный репозиторий, нужно удостовериться, что все перемены зафиксированы в локальном репозитории. После того, как вы внесете изменения локально, вы сможете поделиться ими с помощью . Но прежде чем отправлять какие-либо перемены в удаленную ветку, рекомендуется запустить команду . Это обновит локальную ветвь.
Вынужденная команда push при корректировке коммитов:
# make changes to a repo and git add git commit --amend # update the existing commit message git push --force origin main
Команда применяется для обновления прошлого коммита. Только после этого измененный коммит вынужденно выпускается с помощью команды .
Просмотр удаленного репозитория
Если вы хотите получить побольше информации об одном из удалённых репозиториев, вы можете использовать команду . Выполнив эту команду с каким-либо именем, например, , вы получите следующий результат:
Она выдаёт URL удалённого репозитория, а также информацию об отслеживаемых ветках. Эта команда любезно сообщает вам, что если вы, находясь на ветке , выполните , ветка с удалённого сервера будет автоматически влита в вашу сразу после получения всех необходимых данных. Она также выдаёт список всех полученных ею ссылок.
Это был пример для простой ситуации и вы наверняка встречались с чем-то подобным. Однако если вы используете Git более интенсивно, вы можете получить от гораздо большее количество информации:
Данная команда показывает какая именно локальная ветка будет отправлена на удалённый сервер по умолчанию при выполнении . Она также показывает, каких веток с удалённого сервера у вас ещё нет, какие ветки всё ещё у вас есть, но уже удалены на сервере, и для нескольких веток показано, какие удалённые ветки будут в них влиты при выполнении .
Отправка изменений в удаленный репозиторий (push)
Когда вы хотите поделиться своими наработками, вам необходимо отправить их в удалённый репозиторий. Команда для этого действия простая: . Чтобы отправить вашу ветку на сервер (повторимся, что клонирование обычно настраивает оба этих имени автоматически), вы можете выполнить следующую команду для отправки ваших коммитов:
Эта команда срабатывает только в случае, если вы клонировали с сервера, на котором у вас есть права на запись, и если никто другой с тех пор не выполнял команду . Если вы и кто-то ещё одновременно клонируете репозиторий, затем этот кто-то выполняет команду , а после него выполнить команду попытаетесь вы, то ваш точно будет отклонён. Вам придётся сначала получить изменения и объединить их с вашими и только после этого вам будет позволено выполнить . Обратитесь к главе «Ветвление в Git» для более подробного описания, как отправлять изменения на удалённый сервер.
Переименование файлов в git репозитории
Как и в случае с удалением, переименовать файл в git репозитории можно двумя способами – с использованием и без использования средств операционной системы.
Первый способ. Создадим файл test_main_file.c и добавим его в репозиторий.
> touch test_main_file.c > git add test_main_file.c > git commit -m "add test_main_file.c" add test_main_file.c 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test_main_file.c
Содержимое репозитория после этого будет выглядеть так.
> git ls-tree master 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 test_main_file.c
Переименуем его на test_main.c.
Сделаем это в рабочей директории.
> mv test_main_file.c test_main.c
Теперь отправим изменение в репозиторий.
> git add . > git commit -m "Rename test_main_file.c" Rename test_main_file.c 1 file changed, 0 insertions(+), 0 deletions(-) rename test_main_file.c => test_main.c (100%)
В репозитории и в рабочей директории будет находится только файл test_main.c.
> git ls-tree master 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 test_main.c > ls test_main.c
Второй способ.
В рамках второго способа рассмотрим работу с командой git mv. Переименуем файл test_main.c в main.c. Текущее содержимое репозитория и рабочего каталога.
> git ls-tree master 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 test_main.c > ls test_main.c
Переименуем файл test_main.c на main.c средствами git.
> git mv test_main.c main.c > git commit -m "Rename test_main.c file" Rename test_main.c file 1 file changed, 0 insertions(+), 0 deletions(-) rename test_main.c => main.c (100%)
Имя файла изменилось как в репозитории так и в рабочем каталоге.
> git ls-tree master 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 main.c > ls main.c
<<<Часть 7. Поговорим о HEAD и tree-ish Часть 9. Как удалить коммит в git?>>>
Команда git push по умолчанию
В следующем примере приведен один из стандартных методов публикации локальных вкладов в центральный репозиторий с помощью команды push. Сначала проверяется актуальность вашей локальной главной ветки путем извлечения копии центрального репозитория и перебазирования ваших изменений поверх них. Кроме того, интерактивное перебазирование — это хорошая возможность очистить ваши коммиты перед тем, как делиться ими. Затем все коммиты вашей локальной главной ветки отправляются в центральный репозиторий с помощью команды .
Поскольку мы уже убедились, что локальная главная ветка была обновлена, должно произойти ускоренное слияние, а команда не должна сообщать о каких-либо описанных выше проблемах, связанных с невозможностью выполнения такого слияния.
Опуская пульт и ветку
Когда и удаленный, и ветвь опущены, поведение просто определяется вашим Настройки конфигурации Git:
-
Начиная с Git 2.0, по умолчанию , просто отправит вашу текущую ветку в ее удаленную часть восходящего потока. Пульт определяется по ветке в противном случае по умолчанию используется исходное репо.
-
До версии Git 2.0 настройка по умолчанию, , в основном просто подталкивает все ваши локальные ветки к веткам с тем же именем на пульте дистанционного управления (по умолчанию это origin).
Вы можете прочитать больше настройки, прочитав или онлайн-версию страницы руководства git-config (1).
Удаление файлов из git репозитория и из stage
Удаление файла из stage
Вначале разберемся со stage. Создадим ещё один файл.
> touch main.c
“Отправим” файл main.c в stage.
> git add main.c
Внесем изменения в README.md.
> echo "# README" > README.md
Информацию об этом также отправим в stage.
> git add README.md
Посмотрим на состояние stage.
> git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md new file: main.c
Если нам необходимо убрать из stage, какой-то из этих файлов (main.c или README.md), то для этого можно воспользоваться командой git –rm cashed <filename>, сделаем это для файла main.c.
> git rm --cached main.c rm 'main.c'
Теперь посмотрим на состояние рабочей директории и stage.
> git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md Untracked files: (use "git add <file>..." to include in what will be committed) main.c
Видно, что изменения в файле README.md готовы для коммита, а вот файл main.c перешел в состояние – неотслеживаемый. Отправим main.c в stage и, после этого, сделаем коммит в репозиторий.
> git add main.c > git commit -m "add main.c and do some changes in README.md" add main.c and do some changes in README.md 2 files changed, 1 insertion(+) create mode 100644 main.c
Удаление файлов из git репозитория
Удалить файл из репозитория можно двумя способами: первый – удалить его из рабочей директории и уведомить об этом git; второй – воспользоваться средствами git. Начнем с первого способа. Для начала посмотрим, какие файлы у нас хранятся в репозитории.
> git ls-tree master 100644 blob 7e59600739c96546163833214c36459e324bad0a README.md 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 main.c
Удалим файл main.c из рабочей директории.
> rm main.c > ls README.md
Уведомим об этом систему git.
> git rm main.c rm 'main.c'
Вместо команды git rm можно использовать git add, но само слово add в данном случае будет звучать несколько неоднозначно, поэтому лучше использовать rm. На данном этапе еще можно вернуть все назад с помощью команды git checkout — <filename>, в результате, в нашу рабочую директорию будет скопирован файл из репозитория. Создадим коммит, фиксирующий удаление файла.
> git commit -m "remove main.c" remove main.c 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 main.c
Теперь в репозитории остался только один файл README.md.
> git ls-tree master 100644 blob 7e59600739c96546163833214c36459e324bad0a README.md
Второй способ – это сразу использовать команду git rm без предварительного удаления файла из директории. Вновь создадим файл main.c и добавим его в репозиторий.
> touch main.c > git add main.c > git commit -m "add main.c file" add main.c file 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 main.c > git ls-tree master 100644 blob 7e59600739c96546163833214c36459e324bad0a README.md 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 main.c
Удалим файл из репозитория.
> git rm main.c rm 'main.c' > git commit -m "deleted: main.c file" deleted: main.c file 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 main.c
Файла main.c больше нет в репозитории.
> git ls-tree master 100644 blob 7e59600739c96546163833214c36459e324bad0a README.md
Его также нет и в рабочем каталоге.
> ls README.md
Удалите файл README.md из репозитория самостоятельно.
Просмотр удалённых репозиториев
Для того, чтобы просмотреть список настроенных удалённых репозиториев, вы можете запустить команду . Она выведет названия доступных удалённых репозиториев. Если вы клонировали репозиторий, то увидите как минимум – имя по умолчанию, которое Git даёт серверу, с которого производилось клонирование:
Вы можете также указать ключ , чтобы просмотреть адреса для чтения и записи, привязанные к репозиторию:
Если у вас больше одного удалённого репозитория, команда выведет их все. Например, для репозитория с несколькими настроенными удалёнными репозиториями в случае совместной работы нескольких пользователей, вывод команды может выглядеть примерно так:
Это означает, что мы можем легко получить изменения от любого из этих пользователей. Возможно, что некоторые из репозиториев доступны для записи и в них можно отправлять свои изменения, хотя вывод команды не даёт никакой информации о правах доступа.
Обратите внимание на разнообразие протоколов, используемых при указании адреса удалённого репозитория; мы рассмотрим протоколы подробнее в разделе Установка «Git на сервер» главы 4