Разное

Remote branch git pull: Git fetch remote branch — Stack Overflow

Содержание

Ежедневная работа с Git / Хабр

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

Я постараюсь донести основные идеи, показать как эта VCS помогает разрабатывать проект. Надеюсь, что после прочтения вы сможете ответить на вопросы:

  • можно ли git «подстроить» под тот процесс разработки, который мне нужен?
  • будет ли менеджер и заказчик удовлетворён этим процессом?
  • будет ли легко работать разработчикам?
  • смогут ли новички быстро включиться в процесс?
  • можно ли процесс относительно легко и быстро изменить?

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

Вместо плана

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

Итак, выделю основные шаги:

Окружение

Для работы нам нужно:

  1. Git
  2. Консоль
  3. Человек по ту сторону монитора, который сумеет это всё поставить под свою любимую ось

На текущим момент моё окружение это Debian + KDE + Git + Bash + GitK + KDiff3.
Если вы обнаружили на своём компьютере Windows, то у вас скорее всего будет Windows + msysgit (git-bash) + TortoiseGit и т.д.

Если вы открываете консоль, пишите git и получаете вот это:

справка git

usage: git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [-c name=value] [--help]
           <command> [<args>]

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and merge with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

See 'git help <command>' for more information on a specific command.

Значит вы готовы.

Перестаём бояться экспериментировать

Наверняка, большинство команд уже где-то подсмотрено, какие-то статьи прочитаны, вы хотите приступить но боитесь ввести не ту команду или что-то поломать. А может ещё ничего и не изучено. Тогда просто помните вот это:

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

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

Строго говоря, даже неудачный git push можно исправить.

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

Строим репозитории

В первую очередь нужно понять что такое git-репозиторий? Ответ очень прост: это набор файлов. Папка `.git`. Важно понимать, что это только набор файлов и ничего больше. Раз 20 наблюдал проблему у коллег с авторизацией в github/gitlab. Думая, что это часть git-системы, они пытались искать проблему в конфигруации git, вызывать какие-то git-команды.

А если это просто файлы, то к ним нужно как-то получить доступ, иметь возможность оттуда читать и туда писать? Да! Я называю это «транспортом». Это может и некорректно, но мне так было удобно запомнить. Более правильный вариант: «Протокол передачи данных». Самые распространённые варианты:

  1. FILE — мы имеем прямой доступ к файлам репозитория.
  2. SSH — мы имеем доступ к файлам на сервере через ssh.
  3. HTTP(S) — используем http в качестве приёма/передачи.

Вариантов намного больше. Не важно какой транспорт будет использован, важно чтобы был доступ на чтение или чтение/запись к файлам.
Поэтому, если вы никак не можете клонировать репозиторий с github, и нет в логах никаких подсказок, возможно у вас проблема с транспортом.

В частности, при клонировании вот так:

git clone [email protected]:user/repo.git

урл «превращается» в

git clone ssh://[email protected]:user/repo.git

Т.е. используется SSH и проблемы нужно искать в нём. Как правило, это неправильно настроенный или не найденный ssh-ключ. Гуглить надо в сторону «SSH Auth Key git» или, если совсем по взрослому, проверить, что же происходит:

ssh -vvv [email protected]

Какие протоколы поддерживаются поможет справка (раздел GIT URLS):

git clone --help

Репозиторий можно клонировать, но для начала поиграемся со своими:

  1. Придумаем свой удалённый репозиторий
  2. Сделаем два клона с него, от имени разработчиков (dev1 и dev2)

Кроме самого репозитория есть ещё и workspace, где хранятся файлы с которыми вы работаете. Именно в этой папке лежит сам репозиторий (папка .git ). На серверах рабочие файлы не нужны, поэтому там хранятся только голые репозитории (bare-repo).

Сделаем себе один (будет нашим главным тестовым репозиторием):

$ mkdir git-habr    #создадим папку, чтоб не мусорить
$ cd git-habr
$ git init --bare origin
Initialized empty Git repository in /home/sirex/proj/git-habr/origin/

Теперь клонируем его от имени разработчиков. Тут есть только один нюанс, которого не будет при работе с сервером: git, понимая, что репозитории локальные и находятся на одном разделе, будет создавать ссылки, а не делать полную копию. А нам для изучения нужна полная копия. Для этого можно воспользоваться ключом --no-hardlinks или явно указать протокол:

$ git clone --no-hardlinks origin dev1
Cloning into 'dev1'...
warning: You appear to have cloned an empty repository.
done.
$ git clone --no-hardlinks origin dev2
Cloning into 'dev2'...                                                                                                                                                                                                                                                         
warning: You appear to have cloned an empty repository.                                                                                                                                                                                                                        
done.

Итог: у нас есть 3 репозитория. Там ничего нет, зато они готовы к работе.

Начало GIT

Скандалы! Интриги! Расследования!

  • Git не хранит папки
  • Git не хранит файлы
  • Ревизии (Revision) не имеют порядкового номера
  • Редакции (правки, commits) могут идти не по-порядку
  • В Git нет веток* (с небольшой оговоркой)

Можно дальше продолжить список, но и этого уже достаточно, чтобы задать вполне закономерные вопросы:

Как это всё работает?

Как это всё можно понять и запомнить?

Для этого нужно заглянуть под капот. Рассмотрим всё в общих чертах.

Git. Почти под капотом

Git сохраняет в commit содержимое всех файлов (делает слепки содержимого каждого файла и сохраняет в objects). Если файл не менялся, то будет использован старый object. Таким образом, в commit в виде новых объектов попадут только изменённые файлы, что позволит хорошо экономить место на диске и даст возможность быстро переключиться на любой commit.

Это позволяет понять, почему работают вот такие вот забавные штуки:

$ git init /tmp/test
Initialized empty Git repository in /tmp/test/.git/ 
$ cd /tmp/test
$ cp ~/debian.iso .    # iso весит 168 метров
$ du -sh .git   #считаем размер папки .git
92K     .git
$ git add debian.iso
$ git commit -m "Added iso"
[master (root-commit) 0fcc821] added iso
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 debian.iso
$ du -sh .git   #опять считаем
163M    .git 
# Добавилось. Копируем файлы под другим именем (но то же содержание)
$ cp debian.iso debian2.iso
$ cp debian.iso debian3.iso
$ git add debian2.iso debian3.iso
$ git commit -m "Copied iso"
[master f700ab5] copied iso
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 debian2.iso
 create mode 100644 debian3.iso
$ du -sh .git  #опять считаем
163M    .git  #место почти не изменилось. Это всё тот же объект, просто у него разные имена.

Да, не стоит хранить «тяжёлые» файлы, бинарники и прочее без явной необходимости. Они там останутся навсегда и будут в каждом клоне репозитория.

Каждый коммит может иметь несколько коммитов-предков и несколько дочерних-коммитов:

Мы можем переходить (восстанавливать любое состояние) в любую точку этого дерева, а точнее, графа. Для этого используется git checkout:

git checkout <commit>

Каждое слияние двух и более коммитов в один — это merge (объединение двух и более наборов изменений).
Каждое разветвление — это появление нескольких вариантов изменений.

Кстати, тут хочется отметить, что нельзя сделать тэг на файл/папку, на часть проекта и т.д. Состояние восстанавливается только целиком. Поэтому, рекомендуется держать проекты в отдельном репозитории, а не складывать Project1, Project2 и т.д. просто в корень.

Теперь к веткам. Выше я написал:

В Git нет веток* (с небольшой оговоркой)

Получается, что так и есть: у нас есть много коммитов, которые образуют граф. Выбираем любой путь от parent-commit к любому child-commit и получаем состояние проекта на этот коммит. Чтобы коммит «запомнить» можно создать на него именованный указатель.
Такой именованный указатель и есть ветка (branch). Так же и с тэгом (tag). `HEAD` работает по такому же принципу — показывает, где мы есть сейчас. Новые коммиты являются продолжением текущей ветки (туда же куда и смотрит HEAD).

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

Вот, пожалуй, и всё, что нужно знать из теории на первое время при работе с git. Остальные вещи должны показаться теперь более понятными.

Терминология

index — область зафиксированных изменений, т.е. всё то, что вы подготовили к сохранению в репозиторий.
commit — изменения, отправленные в репозиторий.
HEAD — указатель на commit, в котором мы находимся.
master — имя ветки по-умолчанию, это тоже указатель на определённый коммит
origin — имя удалённого репозитория по умолчанию (можно дать другое)
checkout — взять из репозитория какое-либо его состояние.

Простые правки

Есть две вещи которые должны быть у вас под рукой всегда:

  1. git status
  2. gitk

Если вы сделали что-то не так, запутались, не знаете, что происходит — эти две команды вам помогут.

git status — показывает состояние вашего репозитория (рабочей копии) и где вы находитесь.
gitk — графическая утилита, которая показывает наш граф. В качестве ключей передаём имена веток или --all, чтобы показать все.

Вернёмся к нашим репозиториям, которые создали раньше. Далее обозначу, что один разработчик работает в dev1$, а второй в dev2$.

Добавим README.md:

dev1$ vim README.md
dev1$ git add README.md
dev1$ git commit -m "Init Project"
[master (root-commit) e30cde5] Init Project
 1 file changed, 4 insertions(+)
 create mode 100644 README.md
dev1$ git status
# On branch master
nothing to commit (working directory clean)

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

Он нам это подскажет:

dev1$ git push origin
No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as 'master'.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to '/home/sirex/proj/git-habr/origin'
dev1$ git push origin master 
Counting objects: 3, done.
Writing objects: 100% (3/3), 239 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/sirex/proj/git-habr/origin
 * [new branch]      master -> master

Второй разработчик может получить эти изменения, сделав pull:

dev2$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/sirex/proj/git-habr/origin
 * [new branch]      master     -> origin/master

Добавим ещё пару изменений:

dev1(master)$ vim README.md
dev1(master)$ git commit -m "Change 1" -a
dev1(master)$ vim README.md 
dev1(master)$ git commit -m "Change 2" -a
dev1(master)$ vim README.md 
dev1(master)$ git commit -m "Change 3" -a

Посмотрим, что же мы сделали (запускаем gitk):

Скрытый текст
Выделил первый коммит. Переходя по-порядку, снизу вверх, мы можем посмотреть как изменялся репозиторий:

@@ -2,3 +2,4 @@ My New Project
 --------------
 
 Let's start
+Some changes
@@ -3,3 +3,5 @@ My New Project
 
 Let's start
 Some changes
+Some change 2
+
@@ -2,6 +2,5 @@ My New Project
 --------------
 
 Let's start
-Some changes
-Some change 2
+Some change 3

До сих пор мы добавляли коммиты в конец (там где master). Но мы можем добавить ещё один вариант README.md. Причём делать мы это можем из любой точки. Вот, например, последний коммит нам не нравится и мы пробуем другой вариант. Создадим в предыдущей точке указатель-ветку. Для этого через git log или gitk узнаем commit id. Затем, создадим ветку и переключимся на неё:

dev1(master)$ git branch <branch_name> <commit_id> 
# А можно и git branch <branch_name> HEAD~1 
# но об этом позже
dev1(master)$ git checkout <branch_name>

Для тех, кто любит GUI есть вариант ещё проще: выбрать нужный коммит правой кнопкой мыши -> «create new branch».

Если кликнуть по появившейся ветке, там будет пункт «check out this branch». Я назвал ветку «v2».

Сделаем наши тестовые изменения:

dev1(v2)$ vim README.md 
dev1(v2)$ git commit -m "Ugly changes" -a
[v2 75607a1] Ugly changes
 1 file changed, 1 insertion(+), 1 deletion(-)

Выглядит это так:

Теперь нам понятно, как создаются ветки из любой точки и как изменяется их история.

Быстрая перемотка

Наверняка, вы уже встречали слова fast-forward, rebase, merge вместе. Настало время разобраться с этими понятиями. Я использую rebase, кто-то только merge. Тем «rebase vs merge» очень много. Авторы часто пытаются убедить, что их метод лучше и удобнее. Мы пойдём другим путём: поймём, что же это такое и как оно работает. Тогда сразу станет ясно, какой вариант использовать в каком случае.

Пока, в пределах одного репозитория, сделаем ветвление: создадим файл, положим в репозиторий, из новой точки создадим два варианта файла и попробуем объединить всё в master:

dev1(v2)$ git checkout master 
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 3 commits. # Да, мы впереди по сравнению с master в репозитории origin

Создадим файл collider.init.sh с таким содержанием:

#!/bin/sh


USER=collider


case $1 in
        *)
                echo Uknown Action: $1
        ;;
esac

Добавим, закоммитим и начнём разработку в новой ветке:

dev1(master)$ git add collider.init.sh
dev1(master)$ git commit -m "Added collider init script"
[master 0c3aa28] Added collider init script
 1 file changed, 11 insertions(+)
 create mode 100755 collider.init.sh
dev1(master)$ git checkout -b collider/start # пояснение ниже
Switched to a new branch 'collider/start'
dev1(collider/start)$ git checkout -b collider/terminate # пояснение ниже
Switched to a new branch 'collider/terminate'

git checkout -b <branch_name> создаёт указатель (ветку) на текущую позицию (текущая позиция отслеживается с помощью специального указателя HEAD) и переключается на него.
Или проще: сделать с текущего места новую ветку и сразу же продолжить с ней.

Обратите внимание, что в имени ветки не запрещено использовать символ ‘/’, однако, надо быть осторожным, т.к. в файловой системе создаётся папка с именем до ‘/’. Если ветка с таким названием как и папка существует — будет конфликт на уровне файловой системы. Если уже есть ветка dev, то нельзя создать dev/test.

A если есть dev/test, то можно создавать dev/whatever, но нельзя просто dev.

Итак, создали две ветки collider/start и collider/terminate. Запутались? gitk —all спешит на помощь:


Как видно, мы в одной точке имеем 3 указателя (наши ветки), а изменения в коммите такие:

@@ -0,0 +1,11 @@
+#!/bin/sh
+
+
+USER=collider
+
+
+case $1 in
+	*)
+		echo Uknown Action: $1
+	;;
+esac

Теперь, в каждой ветке напишем код, который, соответственно, будет запускать и уничтожать наш коллайдер. Последовательность действий приблизительно такая:

dev1(collider/start)$ vim collider.init.sh 
dev1(collider/start)$ git commit -m "Added Collider Start Function" -a
[collider/start d229fa9] Added Collider Start Function
 1 file changed, 9 insertions(+)
dev1(collider/start)$ git checkout collider/terminate 
Switched to branch 'collider/terminate'
dev1(collider/terminate)$ vim collider.init.sh
dev1(collider/terminate)$ git commit -m "Added Collider Terminate Function" -a
[collider/terminate 4ea02f5] Added Collider Terminate Function
 1 file changed, 9 insertions(+)

Сделанные измененияcollider/start

@@ -3,8 +3,17 @@
 
 USER=collider
 
+do_start(){
+	echo -n "Starting collider..."
+	sleep 1s
+	echo "ok"
+	echo "The answer is 42. Please, come back again after 1 billion years."
+}
 
 case $1 in
+	start)
+		do_start
+	;;
 	*)
 		echo Uknown Action: $1
 	;;

collider/terminate

@@ -3,8 +3,17 @@
 
 USER=collider
 
+do_terminate() {
+	echo -n "Safely terminating collider..."
+	sleep 1s
+	echo "oops :("
+	
+}
 
 case $1 in
+	terminate)
+		do_terminate
+	;;
 	*)
 		echo Uknown Action: $1
 	;;

Как всегда, посмотрим в gitk —all что наделали:

Разработка закончена и теперь надо отдать все изменения в master (там ведь старый коллайдер, который ничего не может). Объединение двух коммитов, как и говорилось выше — это merge. Но давайте подумаем, чем отличается ветка master от collider/start и как получить их объединение (сумму)? Например, можно взять общие коммиты этих веток, затем прибавить коммиты, относящиеся только к master, а затем прибавить коммиты, относящиеся только к collider/start. А что у нас? Общие коммиты — есть, только коммиты master — нет, только collider/start — есть. Т.е. объединение этих веток — это master + коммиты от collider/start. Но collider/start — это master + коммиты ветки collider/start! Тоже самое! Т.е. делать ничего не надо! Объединение веток — это и есть collider/start!

Ещё раз, только на буквах, надеюсь, что будет проще для восприятия:

master = C1 + C2 +C3

collider/start = master + C4 = C1 + C2 +C3 + C4

master + collider/start = Общие_коммиты(master, collider/start) + Только_у(master) + Только_у(collider/start) = (C1 + C2 +C3) + (NULL) + (C4) = C1 + C2 +C3 + C4

Когда одна ветка «лежит» на другой, то она уже как бы входит в эту, другую ветку, и результатом объединения будет вторая ветка. Мы просто перематываем историю вперёд от старых коммитов к новым. Вот эта перемотка (объединение, при котором делать ничего не надо) и получила название fast-forward.

Почему fast-forward — это хорошо?

  1. При слиянии ничего делать не надо
  2. Автоматическое объединение, причём гарантированное
  3. Конфликты не возможны и никогда не возникнут
  4. История остаётся линейной (как будто объединения и не было), что часто проще для восприятия на больших проектах
  5. Новых коммитов не появляется

Как быстро узнать, что fast-forward возможен? Для этого достаточно посмотреть в gitk на две ветки, которые нужно объединить и ответить на один вопрос: существует ли прямой путь от ветки А к B, если двигаться только вверх (от нижней к верхней). Если да — то будет fast-forward.

В теории понятно, пробуем на практике, забираем изменения в master:

dev1(collider/terminate)$ git checkout master 
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 4 commits.
dev1(master)$ git merge collider/start
Updating 0c3aa28..d229fa9
Fast-forward # то что надо
 collider.init.sh |    9 +++++++++
 1 file changed, 9 insertions(+)

Результат (указатель просто передвинулся вперёд):

Объединение

Теперь забираем изменения из collider/terminate. Но, тот, кто дочитал до сюда (дочитал ведь, да?!) заметит, что прямого пути нет и так красиво мы уже не отделаемся. Попробуем git попросить fast-forward:

dev1(master)$ git merge --ff-only collider/terminate 
fatal: Not possible to fast-forward, aborting.

Что и следовало ожидать. Делаем просто merge:

dev1(master)$ git merge collider/terminate 
Auto-merging collider.init.sh
CONFLICT (content): Merge conflict in collider.init.sh
Automatic merge failed; fix conflicts and then commit the result.

Я даже рад, что у нас возник конфликт. Обычно, в этом момент некоторые теряются, лезут гуглить и спрашивают, что делать.
Для начала:

Конфликт возникает при попытке объединить два и более коммита, в которых в одной и той же строчке были сделаны изменения. И теперь git не знает что делать: то ли взять первый вариант, то ли второй, то ли старый оставить, то ли всё убрать.

Как всегда, две самые нужные команды нам спешат помочь:

dev1(master)$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.
#
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      collider.init.sh
#
no changes added to commit (use "git add" and/or "git commit -a")
dev1(master)$ gitk --all

Мы находимся в master, туда же указывает HEAD, туда же и добавляются наши коммиты.
Файл выглядит так:

#!/bin/sh


USER=collider

<<<<<<< HEAD
do_start(){
        echo -n "Starting collider..."
        sleep 1s
        echo "ok"
        echo "The answer is 42. Please, come back again after 1 billion years."
}

case $1 in
        start)
                do_start
=======
do_terminate() {
        echo -n "Safely terminating collider..."
        sleep 1s
        echo "oops :("

}

case $1 in
        terminate)
                do_terminate
>>>>>>> collider/terminate
        ;;
        *)
                echo Uknown Action: $1
        ;;
esac

Нам нужны оба варианта, но объединять вручную не хотелось бы, правда? Здесь то нам и помогут всякие merge-тулы.
Самый простой способ решить конфликт — это вызвать команду git mergetool. Почему-то не все знают про такую команду.
Она делает примерно следующие:

  1. Находит и предлагает для использования на выбор diff- или merge-программы
  2. Создаёт файл filename.orig (файл как есть до попытки объединить)
  3. Создаёт файл filename.base (какой файл был)
  4. Создаёт файл filename.remote (как его поменяли в другой ветке)
  5. Создаёт файл filename.local (как поменяли его мы)
  6. После разрешения конфликтов всё сохраняется в filename

Пробуем:

dev1(master)$ git mergetool 
merge tool candidates: opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse ecmerge p4merge araxis bc3 emerge vimdiff
Merging:
collider.init.sh

Normal merge conflict for 'collider.init.sh':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

Из-за того что изменения были в одних и тех же местах конфликтов получилось много. Поэтому, я брал везде первый вариант, а второй копировал сразу после первого, но с gui это сделать довольно просто. Вот результат — вверху варианты файла, внизу — объединение (простите за качество):

Сохраняем результат, закрываем окно, коммитим, смотрим результат:

Мы создали новый коммит, который является объединением двух других. Fast-forward не произошёл, потому, что не было прямого пути для этого, история стала выглядеть чуть-чуть запутаннее. Иногда, merge действительно нужен, но излишне запутанная история тоже ни к чему.

Вот пример реального проекта:

Конечно, такое никуда не годится! «Но разработка идёт параллельно и никакого fast-forward не будет» скажете вы? Выход есть!

Перестройка

Что же делать, чтобы история оставалась красивой и прямой? Можно взять нашу ветку и перестроить её на другую ветку! Т.е. указать ветке новое начало и воспроизвести все коммиты один за одним. Этот процесс и называется rebase. Наши коммиты станут продолжением той ветки, на которую мы их перестроим. Тогда история будет простой и линейной. И можно будет сделать fast-forward.
Другими словами: мы повторяем историю изменений с одной ветки на другой, как будто бы мы действительно брали другую ветку и заново проделывали эти же самые изменения.

Для начала отменим последние изменения. Проще всего вернуть указатель master назад, на предыдущее состояние. Создавая merge-commit, мы передвинули именно master, поэтому именно его нужно вернуть назад, желательно (а в отдельных случаях важно) на тот же самый commit, где он был.

Как результат, наш merge-commit останется без какого-либо указателя и не будет принадлежать ни к одной ветке.

Используя gitk или консоль перемещаем наш указатель. Поскольку, ветка collider/start уже указывает на наш коммит, нам не нужно искать его id, а мы можем использовать имя ветки (это будет одно и тоже):

dev1(master)$ git reset --hard collider/start 
HEAD is now at d229fa9 Added Collider Start Function

Что случилось с merge-commit?Когда с коммита или с нескольких коммитов пропадает указатель (ветка), то коммит остаётся сам по себе. Git про него забывает, не показывает его в логах, в ветках и т.д. Но физически, коммит никуда не пропал. Он живёт себе в репозитории как невостребованная ячейка памяти без указателя и ждёт своего часа, когда git garbage collector её почистит.
Иногда бывает нужно вернуть коммит, который по ошибке был удалён. На помощь придёт git reflog. Он покажет всю историю, по каким коммитам вы ходили (как передвигался указатель HEAD). Используя вывод, можно найти id пропавшего коммита, сделать его checkout или создать на коммит указатель (ветку или тэг).
Выглядит это примерно так (история короткая, поместилась вся):

d229fa9 HEAD@{0}: reset: moving to collider/start
80b77c3 HEAD@{1}: commit (merge): Merged collider/terminate
d229fa9 HEAD@{2}: merge collider/start: Fast-forward
0c3aa28 HEAD@{3}: checkout: moving from collider/terminate to master
4ea02f5 HEAD@{4}: commit: Added Collider Terminate Function
0c3aa28 HEAD@{5}: checkout: moving from collider/start to collider/terminate
d229fa9 HEAD@{6}: commit: Added Collider Start Function
0c3aa28 HEAD@{7}: checkout: moving from collider/launch to collider/start
0c3aa28 HEAD@{8}: checkout: moving from collider/terminate to collider/launch
0c3aa28 HEAD@{9}: checkout: moving from collider/stop to collider/terminate
0c3aa28 HEAD@{10}: checkout: moving from collider/start to collider/stop
0c3aa28 HEAD@{11}: checkout: moving from master to collider/start
0c3aa28 HEAD@{12}: commit: Added collider init script
41f0540 HEAD@{13}: checkout: moving from v2 to master
75607a1 HEAD@{14}: commit: Ugly changes
55280dc HEAD@{15}: checkout: moving from master to v2
41f0540 HEAD@{16}: commit: Change 3
55280dc HEAD@{17}: commit: Change 2
598a03a HEAD@{18}: commit: Change 1
d80e5f1 HEAD@{19}: commit (initial): Init Project

Посмотрим, что получилось:

Для того, чтобы перестроить одну ветку на другую, нужно найти их общее начало, потом взять коммиты перестраиваемой ветки и, в таком же порядке, применить их на основную (base) ветку. Очень наглядная картинка (feature перестраивается на master):


Важное замечание: после «перестройки» это уже будут новые коммиты. А старые никуда не пропали и не сдвинулись.

Для самопроверки и понимания: можно было бы вообще не отменять merge-commit. А взять ветку collider/terminate и перестроить на collider/start.

Тогда ветка collider/terminate была бы продолжением collider/start, а master с merge-commit остался бы в стороне. В конце, когда работа была бы готова, master просто переустанавливается на нужный коммит (git checkout master && git reset —hard collider/terminate). Смысл тот же, просто другой порядок действий. Git очень гибок — как хочу, так и кручу.

В теории разобрались, пробуем на практике. Переключаемся в collider/terminate и перестраиваем на тот коммит, куда указывает master (или collider/start, кому как удобнее). Команда дословно «взять текущую ветку и перестроить её на указанный коммит или ветку»:

dev1(master)$ git checkout collider/terminate 
Switched to branch 'collider/terminate'
dev1(collider/terminate)$ git rebase -i master # -i означает в интерактивном режиме, т.е. показать git rebase todo list и дать возможность вмешаться в процесс

Откроется редактор в котором будет приблизительно следующее:

pick 4ea02f5 Added Collider Terminate Function

# Rebase d229fa9..4ea02f5 onto d229fa9
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

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

error: could not apply 4ea02f5... Added Collider Terminate Function

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply 4ea02f5... Added Collider Terminate Function
dev1((no branch))$ git status
# Not currently on any branch.
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      collider.init.sh
#
no changes added to commit (use "git add" and/or "git commit -a")

Решаем конфликты с помощью git mergetool и продолжаем «перестройку» — git rebase —continue. Git в интерактивном режиме даёт нам возможность изменить и комментарий.
Результат:

Теперь уже не сложно обновить master и удалить всё ненужное:

dev1(collider/terminate)$ git checkout master 
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 5 commits.
dev1(master)$ git merge collider/terminate 
Updating d229fa9..6661c2e
Fast-forward
 collider.init.sh |   11 +++++++++++
 1 file changed, 11 insertions(+)
dev1(master)$ git branch -d collider/start 
Deleted branch collider/start (was d229fa9).
dev1(master)$ git branch -d collider/terminate 
Deleted branch collider/terminate (was 6661c2e).

На данном этапе мы удаляли, редактировали, объединяли правки, а на выходе получили красивую линейную историю изменений:

Перерыв

Довольно много информации уже поступило, поэтому нужно остановиться и обдумать всё. На примерах мы познакомились со следующими возможностями git:

  • Лёгкое создание репозиториев
  • Клонирование репозиториев
  • Git работает только с изменениями
  • Один проект/библиотека/плагин — один репозиторий
  • Ветки, комментарии, коммиты легко изменяются
  • Можно выбрать любое состояние и начать от него новую историю
  • Если изменения «лежат на одной прямой» то можно делать fast-forward (перемотка, объединение без конфликтов)

Дальше примеры пойдут по сложнее. Я буду использовать простой скрипт, который будет в файл дописывать случайные строки.

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

Скрипт добавляет случайную строчку к файлу и делает git commit. Это повторяется несколько раз:

dev1(master)$ for i in `seq 1 2`; do STR=`pwgen -C 20 -B 1`; echo $STR >> trash.txt; git commit -m "Added $STR" trash.txt; done
[master e64499d] Added rooreoyoivoobiangeix
 1 file changed, 1 insertion(+)
[master a3ae806] Added eisahtaexookaifadoow
 1 file changed, 1 insertion(+)
Передача и приём изменений

Настало время научиться работать с удалёнными репозиториями. В общих чертах, для работы нам нужно уметь:

  • добавлять/удалять/изменять информацию о удалённых репозиториях
  • получать данные (ветки, тэги, коммиты)
  • отправлять свои данные (ветки, тэги, коммиты)

Вот список основных команд, которые будут использоваться:

  1. git remote — управление удалёнными репозиториями
  2. git fetch — получить
  3. git pull — тоже самое что git fetch + git merge
  4. git push — отправить
git remote

Как отмечалось выше, origin — это имя репозитория по умолчанию. Имена нужны, т.к. репозиториев может быть несколько и их нужно как-то различать. Например, у меня была копия репозитория на флешке и я добавил репозиторий flash. Таким образом я мог работать с двумя репозиториями одновременно: origin и flash.

Имя репозитория используется как префикс к имени ветки, чтоб можно было отличать свою ветку от чужой, например master и origin/master

Небольшой трюк

master в репозитории origin будет показываться как origin/master. Но как уже известно, можно дать ветке имя содержащее ‘/’.

Т.е. можно создать ветку с именем «origin\/master«, которая будет являться просто обычной веткой и ничего общего с удалённой веткой master иметь не будет. Git послушный, сделает всё, что вы попросите. Конечно, не стоит так делать.

В справке по git remote достаточно хорошо всё описано. Как и ожидается, там есть команды: add, rm, rename, show.
show покажет основные настройки репозитория:

dev1(master)$ git remote show origin 
* remote origin
  Fetch URL: /home/sirex/proj/git-habr/origin
  Push  URL: /home/sirex/proj/git-habr/origin
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (fast-forwardable)

Чтобы добавить существующий репозиторий используем add:

git remote add backup_repo ssh://user@myserver:backups/myrepo.git # просто пример
git push backup_repo master
git fetch

Команда говорит сама за себя: получить изменения.
Стоит отметить, что локально никаких изменений не будет. Git не тронет рабочую копию, не тронет ветки и т.д.
Будут скачены новые коммиты, обновлены только удалённые (remote) ветки и тэги. Это полезно потому, что перед обновлением своего репозитория можно посмотреть все изменения, которые «пришли» к вам.

Ниже есть описание команды push, но сейчас нам нужно передать изменения в origin, чтобы наглядно показать как работает fetch:

dev1(master)$ git push origin master 
Counting objects: 29, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (27/27), 2.44 KiB, done.
Total 27 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (27/27), done.
To /home/sirex/proj/git-habr/origin
   d80e5f1..a3ae806  master -> master

Pro Git: Основы Git — Работа с удалёнными репозиториями

Чтобы иметь возможность совместной работы над каким-либо Git-проектом, необходимо знать, как управлять удалёнными репозиториями. Удалённые репозитории — это модификации проекта, которые хранятся в интернете или ещё где-то в сети. Их может быть несколько, каждый из которых, как правило, доступен для вас либо только на чтение, либо на чтение и запись. Совместная работа включает в себя управление удалёнными репозиториями и помещение (push) и получение (pull) данных в и из них тогда, когда нужно обменяться результатами работы. Управление удалёнными репозиториями включает умение добавлять удалённые репозитории, удалять те из них, которые больше не действуют, умение управлять различными удалёнными ветками и определять их как отслеживаемые (tracked) или нет и прочее. Данный раздел охватывает все перечисленные навыки по управлению удалёнными репозиториями.

Чтобы разобрать примеры этой главы я создал удаленный репозитарий TestRemote на GitHub, а затем склонировал его себе.

Отображение удалённых репозиториев

Чтобы просмотреть, какие удалённые серверы у вас уже настроены, следует выполнить команду git remote. Она перечисляет список имён-сокращений для всех уже указанных удалённых дескрипторов. Если вы склонировали ваш репозиторий, у вас должен отобразиться, по крайней мере, origin — это имя по умолчанию, которое Git присваивает серверу, с которого вы склонировали:

Чтобы посмотреть, какому URL соответствует сокращённое имя в Git, можно указать команде опцию -v:

Добавление удалённых репозиториев

Чтобы добавить новый удалённый Git-репозиторий под именем-сокращением, к которому будет проще обращаться, выполните git remote add [сокращение] [url]:

Теперь вы можете использовать в командной строке имя tr вместо полного URL.

Например, я сделал некоторые изменения файла README.md и теперь загрузим их себе в локальный репозиторий командой git fetch:

Теперь ветка изменений с сервера доступна локально как tr/mater. Вы можете слить (merge) её в одну из своих веток или перейти на эту ветку, если хотите её проверить.

Тут надо отметить, что между командами git pull и git fetch есть разница, но об этом чуть позже.

На данный момент, если мы посмотрим содержимое файла README.md в рабочем каталоге, то оно будет точно такое же, как было до команды git fetch. Это потому, что мы в данный момент находимся в ветке master локального репозитария, которая не была изменена.

Чтобы посмотреть все существующие ветки можно дать команду git branch с ключом –a, который покажет все ветки репозитория.

Здесь активная ветка обозначена звёздочкой. А так же мы видим ветку которую мы притянули командой git fetch – это ветка remotes/tr/master. Собственно об этом нам команда git fetch и сообщила после выполнения.

Переключится на ветку можно командой git checkout <имя ветки>

И так мы переключились на ветку которую стянули командой git fetch, о чем нам выдалось сообщение и рассказали какие файлы были обновлены. Это файл README.md. Теперь в рабочем каталоге мы можем посмотреть измененное содержимое этого файла (мы его меняли непосредственно на GitHub).

Мы так же можем переключится обратно на нашу ветку master

Теперь будем разбираться с разницей между fetch и pull.

Fetch и Pull

Как вы только что узнали, для получения данных из удалённых проектов, следует выполнить:

$ git fetch [имя удал. сервера]

Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта. Теперь эти ветки в любой момент могут быть просмотрены или слиты (объединены).

Когда вы клонируете репозиторий, команда clone автоматически добавляет этот удалённый репозиторий под именем origin. Таким образом, git fetch origin извлекает все наработки, отправленные (push) на этот сервер после того, как вы склонировали его (или получили изменения с помощью fetch). Важно отметить, что команда fetch забирает данные в ваш локальный репозиторий, но не сливает (не объединяет) их с какими-либо вашими наработками и не модифицирует то, над чем вы работаете в данный момент. Вам необходимо вручную слить эти данные с вашими, когда вы будете готовы.

Если у вас есть ветка, настроенная на отслеживание удалённой ветки, то вы можете использовать команду git pull. Она автоматически извлекает и затем сливает (объединяет) данные из удалённой ветки в вашу текущую ветку. Этот способ может для вас оказаться более простым или более удобным. К тому же по умолчанию команда git clone автоматически настраивает вашу локальную ветку master на отслеживание удалённой ветки master на сервере, с которого вы клонировали (подразумевается, что на удалённом сервере есть ветка master). Выполнение git pull, как правило, извлекает (fetch) данные с сервера, с которого вы изначально склонировали, и автоматически пытается слить (объеденить) (merge) их с кодом, над которым вы в данный момент работаете.

Push

Когда вы хотите поделиться своими наработками, вам необходимо отправить (push) их в главный репозиторий. Команда для этого действия простая: git push [удал. сервер] [ветка]. Чтобы отправить вашу ветку master на сервер origin (повторимся, что клонирование, как правило, настраивает оба этих имени автоматически), вы можете выполнить следующую команду для отправки наработок на сервер:

$ git push origin master

Эта команда срабатывает только в случае, если вы клонировали с сервера, на котором у вас есть права на запись, и если никто другой с тех пор не выполнял команду push. Если вы и кто-то ещё одновременно клонируете, затем он выполняет команду push, а затем команду push выполняете вы, то ваш push точно будет отклонён. Вам придётся сначала вытянуть (pull) их изменения и объединить с вашими. Только после этого вам будет позволено выполнить push.

Я выполнил команды pull и объединил изменения для файла README.md и затем залил их на сервер GitHub. Скрин привожу просто для информации чтобы было видно как это делается.

Более подробно как отправлять (push) данные на удалённый сервер мы рассмотрим чуть позже.

Инспекция удалённого репозитория

Если хотите получить побольше информации об одном из удалённых репозиториев, вы можете использовать команду git remote show [удал. сервер]. Если вы выполните эту команду с некоторым именем, например, origin, вы получите что-то подобное:

Она выдаёт URL удалённого репозитория, а также информацию об отслеживаемых ветках. Эта команда любезно сообщает вам, что если вы, находясь на ветке master, выполните git pull, ветка master с удалённого сервера будет автоматически влита в вашу сразу после получения всех необходимых данных. Она также выдаёт список всех полученных ею ссылок.

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

Удаление и переименование удалённых репозиториев

Для переименования ссылок в новых версиях Git’а можно вылолнить git remote rename, это изменит сокращённое имя, используемое для удалённого репозитория. Например, если вы хотите переименовать tr в tstrmt, вы можете сделать это следующим образом:

Стоит упомянуть, что это также меняет для вас имена удалённых веток. То, к чему вы обращались как tr/master, стало tstrmt/master.

Если по какой-то причине вы хотите удалить ссылку (вы сменили сервер или больше не используете определённое зеркало, или, возможно, контрибьютор перестал быть активным), вы можете использовать git remote rm:

инструкция по работе. Команды. Совместная работа.

 Что такое коммит?

Коммит — очередное зафиксированное состояние проекта, «единица» версии.
Все коммиты (кроме первого) должны наследоваться от предыдущего коммита, образуя таким образом древовидную структуру, как изображено на рисунке ниже (кружки — коммиты).

Как видно из иллюстрации, проект может разветвляться, например если два разработчика параллельно работают и каждый создаёт свои коммиты. Чтобы не возникало полного хаоса и можно было ориентироваться в происходящем вводят понятие ветки
Ветка — по большому счёту просто именованная ссылка на некий коммит, указывающая на конец очередного ответвления от главной центральной ветки (по умолчанию она зовётся master). Как правило, репозиторий работает в привязке к какой-то ветке и при создании нового коммита, он присоединяется к тому, на который ссылается ветка, и ветка начинает указывать на новый коммит. На картинке выше помимо master есть ветки Little Feature и Big Feature.

Установка

Linux — нужно просто открыть терминал и установить приложение при помощи пакетного менеджера вашего дистрибутива. Для Ubuntu команда будет выглядеть следующим образом:

sudo apt-get install git

Windows — мы рекомендуем git for windows, так как он содержит и клиент с графическим интерфейсом, и эмулятор bash.

Настройка

Первым делом до начала работы, нужно внести глобальные настройки:

git config —global user.name «My Name»
git config —global user.email [email protected]

Репозиторий

Итак, вот у вас уже есть git. Теперь нужно создать хранилище версий для него. Запомните, это хранилище называется репозиторий (англ. repository) — при случае можете вставить где-нибудь это словечко. В зависимости от того, какая у вас оболочка, соответствующей командой создайте новую директорию, откройте ее (в командной строке, она же оболочка, а не проводником или чем-то подобным) и выполните:

git init

Все, локальный репозиторий в этой папке создан. То, что здесь сейчас хранится, будет бекапом, поэтому, чтобы его не испортить, создадим рабочую копию (англ. check out)локальной версии:

git clone [url]

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

git clone username@host:/path/to/repository

Иногда нужно склонировать только конкретную ветку, тогда:

git clone —branch=branch-name http://whatever.git

Еще иногда может потребоваться склонировать репозиторий без многолетней истории его коммитов, тогда нужно использовать параметр —depth=5, где 5 — количество коммитов от последнего:

git clone —depth=1 —branch=branch-name http://whatever.git

Есть несколько условных этапов работы с репозиторием (с файлами в нём):

  1. Создание репозитория (git init) или (git clone адресс_репозитория ), если копируем удалённый
  2. Делаем изменения
  3. Помещаем файлы под VCS-отслеживание (git add)
  4. Фиксируем (коммитим) изменения (git commit)
  5. Заливаем (пушим) их на удалённое хранилище (git push)

Создание коммита

Получение статуса репозитория:

git status

Добавление файлов в коммит:

git add [имя_файла]

Добавление всех файлов в коммит:

git add *

Создание коммита:

git commit -m «Commit message»

Файл(-ы) находятся в HEAD вашей рабочей локальной копии. В вашем удаленном репозитории их все еще нет.
Пуш в репозиторий:

git push origin master

Работа с удалёнными репозиториями:

git remote add origin [сервер]

Ветвление

Создание новой ветки
Есть разные принципы модели ветвления в git. Одна из них: Новая задача — новая ветка. О другой поговорим далее.
Создание новой ветки:

git checkout -b [новая_ветка]

Переключение между ветками
Выбор ветки:

git checkout [репозиторий]/[ветка]

Удаление ветки:

git branch -d [ветка]

Обязательно нужно делать пуш изменений в общий репозиторий:

git push origin [ветка]

Запрос изменений с сервера

Чтобы обновить локальный репозиторий до последнего коммита, нужно сделать “пулл”:

git pull [ветка] — например origin master

Загрузить изменения с конкретной ветки:

git fetch <remote_name> <branch_name>

Слияние веток

Чтобы слить ветку в ту, с которой вы сейчас работаете, используйте:

git merge [ветка]

Ветки можно сравнить:

git diff [одна_ветка] [другая_ветка]

Обновить локальный репозиторий до нового коммита:

git pull

Теги:

git tag [tag] [первые_десять_символов_соответствующего_коммита]

Историю репозитория — его лог:

git log

Откат мерджа
Если проблема только в одном файле, то вот вам Ctrl Z для HEAD’a:

git checkout — [имя_файла]

Но если проблема находится в локальном репозитории, то зачистите там все и верните версию с сервера:

git fetch origin git reset —hard origin/master

 

Разрешение конфликтов при слиянии

Мы попытаемся слить две ветки под названием 1_branch и 1_branch.
Где есть изменения в одних и тех же файлах. Если попытаться слить две ветки, они получат сообщение об ошибке:

git merge 1_branch
Auto-merging print_array.js
CONFLICT (content): Merge conflict in print_array.js
Automatic merge failed; fix conflicts and then commit the result.

Система не смогла разрешить конфликт автоматически, значит, это придется сделать разработчикам. Приложение отметило строки, содержащие конфликт:
Над разделителем ======= мы видим последний (HEAD) коммит, а под ним — конфликтующий. Таким образом, мы можем увидеть, чем они отличаются и решать, какая версия лучше. Или вовсе написать новую. В этой ситуации мы так и поступим, перепишем все, удалив разделители, и дадим git понять, что закончили.Когда все готово, нужно закоммитить изменения, чтобы закончить процесс:

git add -A
git commit -m «Array printing conflict resolved.»

Пример:
Спойлер:

Короткая и простая история коммитов.

git checkout -b iss53

Создание новой ветки / указателя.

Сделали новый коммит:

Ветка iss53 передвинулась вперёд во время работы.

Создание хот-фикса:
git checkout master
git checkout -b hotfix

Ветка для решения срочной проблемы базируется на ветке master.

Слияние веток:
git checkout master
git merge hotfix
git merge iss53

Git автоматически создаёт новый коммит, содержащий результаты слияния.

Настройка .gitignore

В большинстве проектов есть файлы или целые директории, в которые мы не хотим (и, скорее всего, не захотим) коммитить. Мы можем удостовериться, что они случайно не попадут в git add -A при помощи файла .gitignore

  1. Создайте вручную файл под названием .gitignore и сохраните его в директорию проекта.
  2. Внутри файла перечислите названия файлов/папок, которые нужно игнорировать, каждый с новой строки.
  3. Файл .gitignore должен быть добавлен, закоммичен и отправлен на сервер, как любой другой файл в проекте.

Вот хорошие примеры файлов, которые нужно игнорировать:

  • Логи
  • Артефакты систем сборки
  • Папки node_modules в проектах node.js
  • Папки, созданные IDE, например, Netbeans или IntelliJ
  • Разнообразные заметки разработчика.

Файл .gitignore, исключающий все перечисленное выше, будет выглядеть так:
Спойлер:

*.log
build/
node_modules/
.idea/
my_notes.txt

Удачная модель ветвления для Git

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

  • master —  создаётся при инициализации репозитория, считаем ветку origin/master главной.
  • develop — ветвь origin/develop мы считаем главной ветвью для разработки.

Вспомогательные ветви

  • Ветви функциональностей (Feature branches)
  • Ветви релизов (Release branches)
  • Ветви исправлений (Hotfix branches)

Ветви функциональностей (feature branches)Могут порождаться от: develop
Должны вливаться в: develop
Соглашение о наименовании: всё, за исключением master, develop, release-* или hotfix-*

При начале работы над новой функциональностью делается ответвление от ветви разработки (develop).

git checkout -b myfeature develop

Ветви релизов (release branches)
Могут порождаться от: develop
Должны вливаться в: develop и master
Соглашение о наименовании: release-*

Ветвь релиза создаётся из ветви разработки (develop).
Закрытие ветви релиза
Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это по определению новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесённые исправления багов.

git checkout master

Switched to branch ‘master’
git merge —no-ff release-1.2
Merge made by recursive.
(Отчёт об изменениях)

git tag -a 1.2

Теперь релиз издан и помечен тегом.

Чтобы сохранить изменения и в последующих релизах, мы должны влить эти изменения обратно в разработку. Делаем это так:

git checkout develop

Switched to branch ‘develop’

git merge —no-ff release-1.2

Merge made by recursive.
(Отчёт об изменениях)

Этот шаг, в принципе, может привести к конфликту слияния (нередко бывает, что к причиной конфликта является изменение номера версии проекта). Если это произошло, исправьте их и издайте коммит.

Теперь мы окончательно разделались с веткой релиза. Можно её удалять, потому что она нам больше не понадобится:

git branch -d release-1.2

Deleted branch release-1.2 (was ff452fe).

Ветви исправлений (hotfix branches)
Могут порождаться от: master
Должны вливаться в: develop и master
Соглашение о наименовании: hotfix-*

Ветви исправлений (hotfix branches) создаются из главной (master) ветви.

Заключение

Можно сказать есть такие пути работы с гит:
1) разбить деятельность на задачи, и каждой задаче создать свою ветку, а потом мерджить
2) работать в одной ветке, и обновлять свой локальный репозиторий, с последующим его залитием

Краткая справка команд:

git pull — обновить данные из серверного репозитория
git add — добавить в список «на коммит»
git commit — создание пакета (коммита) с изменениями 
git push — залить за серверный (удалённый) репозиторий
git merge BRANCH — слияние ветки в который ты находишься, с веткой BRANCH

ПО

http://git-scm.com/downloads  консольный клиент
https://desktop.github.com/      github
https://www.gitkraken.com/     https://www.gitkraken.com/

Вопросы:
Есть репозиторий, над ним работают два человека: первый клонирует репозиторий, вносит правки и пушит; второй в это же время тоже начал работу, склонировал, но запушить не может, так как 1й уже внес правки. Как быть?

Ответ:
Ты делаешь комит и когда пытается сделать пуш, гит говорит, что надо сначала стянуть изменения. Когда стягиваешь изменения, они автоматом мержатся со своими изменениями и потом уже можешь сделать свой пуш.
Если правите разные файлы или разные строчки в одном и том же файле, то гит смержит изменения автоматически.

Теперь случай посложнее, когда вы правили одни и те же строчки в одних и тех же файлах:

Тут гит сам не справится. сценарий такой. 1й делает изменения и пушит их в репозиторий. 2й делает изменения и пытается сделать пуш, но гит говорит стянуть сначала новые изменения. Когда он стягивает изменения, гит говорит ему что есть конфликты и надо бы их поправить; пишет в каких файлах; нужно зайти в эти файлы, там будут специальные метки:
<================
изменения_друга
===============>
твои_изменения
==========

В тех местах, где гит не смог сам смержить 2му придется выбирать что оставить или переписать эти куски так, чтобы работало правильно.

Потом сделать:
git add .
git commit
(в комите можно написать комментарий типа «фикс конфликтов»)
git push

После этого ваши изменения будут залиты.

В чем разница между Fetch и Pull?

Быстрое объяснение

git pull — это, по сути, команда git fetch, после которой сразу же следует git merge. 

git fetch получает изменения с сервера и сохраняет их в каталог refs/remotes/. Это никак не влияет на локальные ветки и текущие изменения. А git merge уже вливает все эти изменения в локальную копию.

Подробное объяснение

Git fetch

Для получения данных из удалённых проектов, следует выполнить:

$ git fetch [имя удал. сервера]

Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта. Теперь эти ветки в любой момент могут быть просмотрены или слиты.

Когда вы клонируете репозиторий, команда clone автоматически добавляет этот удалённый репозиторий под именем origin. Таким образом, git fetch origin извлекает все наработки, отправленные (push) на этот сервер после того, как вы склонировали его (или получили изменения с помощью fetch). Важно отметить, что команда fetch забирает данные в ваш локальный репозиторий, но не сливает их с какими-либо вашими наработками и не модифицирует то, над чем вы работаете в данный момент. Вам необходимо вручную слить этот код с вашим кодом в рабочей директории, когда вы будете готовы, с помощью git merge.

Возможно, более яснее станет, что делает git fetch, если посмотреть на эту картинку:

Git pull

Если у вас есть ветка, настроенная на отслеживание удалённой ветки, то вы можете использовать команду git pull. Она автоматически скачивает и затем вливает данные из удалённой ветки в вашу текущую ветку. Этот способ может для вас оказаться более простым или более удобным. К тому же по умолчанию команда git clone автоматически настраивает вашу локальную ветку master на отслеживание удалённой ветки master на сервере, с которого вы клонировали (подразумевается, что на удалённом сервере есть ветка master). Выполнение git pull, как правило, извлекает (fetch) данные с сервера, с которого вы изначально склонировали, и автоматически пытается слить (merge) их с кодом, над которым вы в данный момент работаете.

То есть, работа git pull состоит из двух стадий. Первая стадия — это то же самое что и git fetch, а вторая стадия — это мердж с кодом в рабочей директории. Вот так:

gitlab merge request, как сделать и принять merge request

gitlab merge request — позволяет перед коммитом в master ветку отправить внесенные изменения другим разработчикам проекта, это аналог pull request в git. merge request позволяет предотвратить внесение некорректных изменений, которые сломают проект.

 

 

Зайдя в Gitlab от имени пользователя, который может работать с проектом скачаем исходный код через git clone

 

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

git clone git@ip-address:root/myproject.git

 

Теперь на локальном компьютере присутствуют скрипты проекта, или один скрипт index.py как в примере.

 

Переходим в каталог

cd myproject/

 

Теперь можно создать новую ветку

git checkout -b update-code

 

В ней вносим изменения

mcedit index.py

Открыв файл в текстовом редакторе добавим комментарий

Затем добавляем все содержимое каталога на staging

git add .

 

Коммитим изменения

git commit -m ‘updated code’

 

И заливаем в ветку update-code

git push origin update-code

Total 3 (delta 1), reused 0 (delta 0)
remote: To create a merge request for update-code, visit:
remote: http://ip-address/root/myproject/merge_requests/new?merge_request%5Bsource_branch%5D=update-code
remote:
To ip-address:root/myproject.git
* [new branch] update-code -> update-code

 

После обновления страницы в интерфейсе Gitlab будет отображаться вторая ветка

 

Рядом с именем ветки есть кнопка Merge request

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

 

Также можно установить, что нужно чье-либо одобрение для принятия Merge-request и слияния с веткой master.

 

После заполнения полей формы нужно нажать «Submit merge request» внизу.

 

Теперь тот кому отправлен MR получит оповещение и сможет увидеть все внесенные изменения, затем закрыть MR, выполнить слияние с master или начать дискуссию.

В интерфейсе есть кнопки «Open in Web IDE» и «Check out branch«

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

 

Если выбрать «Check out branch» — отобразится инструкция с командами, позволяющими скачать изменений на локальный компьютер, исправить все конфликты и загрузить в репозиторий.

 

В случае если изменения корректны и не нанесут ущерба проекту можно нажать Merge.

 

 

В консоли когда merge выполнен, можно переключиться на master и забрать через  pull изменения.

git checkout master

 

git pull origin master

 

Изменения будут залиты в master. Найдя MR всегда можно воспользоваться опцией revert для отмены.

GitHub: руководство для начинающего контрибьютора

Представим себе что вы хотите исправить ошибку или добавить фичу в проект на GitHub.

Если это что-то простое, вроде опечатки в README.md, то это делается в два клика прямо на GitHub. Поговорим о более сложном случае, когда нужно не просто исправить ошибку, но и запустить необходимые скрипты для проверки, разбить работу на несколько коммитов, и так далее.

Спешите? Все команды сразу.

К делу

Начать следует с форка репозитория проекта, который планируется дополнить. Это делается нажатием кнопки «Fork» на странице репозитория прямо на GitHub.

Чтобы далеко не искать подходящий пример, сделайте форк репозитория с файлами для статьи о внедрении PHPUnit.

Затем склонируйте себе локально исходный репозиторий. Важно клонировать не ваш форк, а репозиторий исходного проекта. С таким подходом ветка master будет постоянно указывать на исходный проект.

$ git clone https://github.com/sanmai/phpunit-primer

Перейдем в каталог с клоном и посмотрим, какие удалённые репозиторий настроены.

$ cd phpunit-primer
$ git remote -v
origin  https://github.com/sanmai/phpunit-primer (fetch)
origin  https://github.com/sanmai/phpunit-primer (push)

За редким исключением, всем удалённым репозиториям в Git присваиваются имена. По умолчанию первый добавленный репозиторий называется origin, но в нашем случае это не подходит. Репозиторий исходного проекта переименуем в upstream, из чего будет понятно что оттуда делается только pull.

$ git remote rename origin upstream

Для верности можно бесповоротно сломать возможность сделать push, запретить выгружать любые коммиты обратно. В команде ниже вместо disabled можно использовать любой другой несуществующий URL.

$ git remote set-url --push upstream disabled

С такой настройкой сделать push будет просто невозможно.

$ git remote -v
upstream    https://github.com/sanmai/phpunit-primer (fetch)
upstream    disabled (push)
$ git push
fatal: 'disabled' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

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

Мы готовы к тому, чтобы подключить ваш форк, упомянув его SSH-ссылкой.

$ git remote add origin [email protected]:username/phpunit-primer.git

Ваш форк в Git будет называться origin, с тем расчетом чтобы команды в обычных подсказках, которые показывает Git, работали без необходимости что-то менять перед копированием и вставкой. Как, например, при первом пуше из новой ветки:

$ git push
fatal: The current branch test has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin test

Что ещё?

Как правило, недостаточно запретить пушить в master. Можно по ошибке сделать коммит в master, затем начать новую ветку и получить очень некрасивую историю и отвергнутый PR.

Избежать этого можно если запретить коммиты в master хуком .git/hooks/pre-commit с таким содержанием:

#!/bin/sh
set -e -x
test $(git rev-parse --abbrev-ref HEAD) != "master"

С таким хуком при попытке коммита в master будет выводиться ошибка:

$ git checkout master
$ git commit
+ git rev-parse --abbrev-ref HEAD
+ test master != master

Готово!

Все готово к началу работы. Дальше каждый раз одно и то же.

  1. Загружаем последние изменения с исходного проекта в ветку master.

    $ git checkout master
    $ git pull
    
  2. Делаем новую ветку с понятным названием на основе ветки master.

    $ git checkout -b fix-for-issue-42
    Switched to a new branch 'fix-for-issue-42'
    
  3. Вносим всевозможные изменения, запускаем тесты и так далее.

    $ composer install
    $ git diff
    $ git add -p
    $ git diff --cached
    $ php vendor/bin/phpunit
    $ git commit
    
  4. Выгружаем коммиты с работой из ветки обратно на GitHub.

    $ git push --set-upstream origin fix-for-issue-42
    Total 0 (delta 0), reused 0 (delta 0)
    To github.com:username/phpunit-primer.git
    * [new branch]      fix-for-issue-42 -> fix-for-issue-42
    Branch 'fix-for-issue-42' set up to track remote branch 'fix-for-issue-42' from 'origin'.
    
  5. Открываем PR, ждем одобрения ведущих разработчиков.

  6. Радуемся сообщению о принятии изменений.

Всё сразу

Если задать входные данные переменными:

UPSTREAM=example/example
MASTER=$USER/$(basename $UPSTREAM)

То все команды для начала работы и настройки копии будут следующие:

git clone https://github.com/$UPSTREAM
cd $(basename $UPSTREAM)
git remote rename origin upstream
git remote set-url --push upstream disabled
git remote add origin [email protected]:$MASTER.git
tee .git/hooks/pre-commit <<'EOF'
#!/bin/sh
set -e -x
test $(git rev-parse --abbrev-ref HEAD) != "master"
EOF
chmod +x .git/hooks/pre-commit

Как вытащить удаленную ветку Git? [3 примера команды / GUI]

Прежде чем объяснять, что такое команда Git pull и как она работает, позвольте мне показать вам простую команду, которая извлекает удаленную ветку из репозитория Github в локальное репозиторий.

Команда:

$ git pull origin master

Команда должна получить содержимое из установленного удаленного репозитория в локальное репозиторий.

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

$ git remote –v

На снимке экрана ниже показаны текущие URL-адреса, установленные на Github на моем Git Bash:

Пошаговое руководство по созданию и извлечению удаленной ветви

Если вы новичок, то это руководство специально для вас.В этом разделе я покажу вам шаг за шагом создание онлайн-репозитория (на Github), добавление файлов, а затем с помощью команды pull в Git Bash мы извлечем и загрузим ветку в нашем локальном репозитории — так что продолжайте читать .

Создание репозитория на Github

Это просто и понятно — перейдите на сайт Github, создайте учетную запись (если вы еще не сделали этого), и вы перейдете к созданию нового репозитория.

Я создал новое репо с именем tst-pull-2 для нашей демонстрации.

По умолчанию он содержит одну ветку, т.е. master , и, поскольку я создал репозиторий с README, он также содержит этот файл.

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

Выполнение выборки и слияния

Хотя наша тема — Git pull, почему я использовал два других имени команд в заголовке выше? Это связано с тем, что команда pull Git представляет собой комбинацию команд fetch и merge .Я объясню это после выполнения приведенной ниже команды вытягивания.

Для загрузки содержимого удаленного репо запустите команду Git pull следующим образом.

Добавить удаленный источник

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

$ git удаленное добавление источника «https://github.com/git-test-jaz/tst-pull-2.git»

Измените URL-адрес, если вы используете другое репо.

(Чтобы узнать больше о том, как открыть Git Bash и установить путь, посетите этот учебник)

После добавления источника давайте запустим команду git pull для загрузки удаленного репо:

$ git pull origin master

Эта команда должна загрузить все файлы из удаленного репозитория в локальный.Git Bash должен отображать такие сообщения:

На графике вы можете увидеть вывод двух команд. Один предназначен для команды git pull, а другой отображает файлы в главной ветке с помощью команды $ ls .

Как видите, отображаются все четыре файла, как в нашем удаленном репозитории на рисунке выше.

Точно так же вы можете перейти в локальную активную папку, в которой вы запустили Git Bash, и увидеть локальное репо. Вот что содержится в нашей демонстрационной папке «pull-tst» в системе Windows после выполнения команды pull:

Итак, как работает команда git pull?

Возвращаясь к нашему вопросу, почему мы использовали термины «выборка» и «фиксация», говоря о команде извлечения.Причина в том, что команда pull — это комбинация команд fetch и commit.

Когда мы запустили $ git pull в разделе выше, команда pull выполнила git fetch и загрузила контент из удаленной ветви.

После этого следует выполнение git merge командой pull.

Как насчет использования команды Pull для существующих репозиториев?

В приведенном выше разделе мы узнали, как создать онлайн-репо и вытащить его основную ветвь в локальное репо с помощью команды pull Git.

Как насчет того, чтобы внести изменения в существующее репо / ветку на удаленном сервере, а затем использовать команду pull.

Например, мы добавили еще два файла изображений после выполнения вышеуказанной операции. Для пояснения я также изменил содержимое файла demo1.txt. Итак, вот так выглядит наше онлайн-репо на Github:

Если вы снова запустите эту команду в Git Bash:

$ git pull origin master

Отображается следующее сообщение:

Точно так же в локальной папке в системе Windows должны отображаться только что добавленные изображения, а также обновленный текстовый файл.

Извлечь без новой фиксации слияния

Следующая команда pull загружает / извлекает содержимое удаленного репозитория. Однако он не создаст новую фиксацию слияния:

$ git pull –no-commit

Выполнение операции извлечения через графический интерфейс Git

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

Однако графический интерфейс для Git не предоставляет прямой возможности для выполнения команды pull (как и многие другие команды).В нем есть пункты меню для «выборки» и «слияния», которые вы можете выполнять отдельно.

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

Шаг 1. Откройте графический интерфейс для Git

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

Для этого щелкните правой кнопкой мыши после открытия содержимого папки и выберите параметр «Git GUI Here» в системе Windows.

Шаг 2 — Готово с изменениями в удаленном репо?

Перед использованием графического интерфейса убедитесь, что все изменения внесены в удаленный репозиторий.В качестве примера я добавил еще один файл изображения, а также обновил содержимое файла «demo1.txt», чтобы наша операция извлечения с графическим интерфейсом Git загружала и объединяла два изменения. На рисунке ниже показаны эти два изменения:

Шаг 3. Выполнение операции выборки из графического интерфейса Git

Перейдите в графический интерфейс Git и найдите «Remote» в верхнем меню. Щелкните по нему, и он должен показать «Fetch From» -> Origin.

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

После появления зеленой полосы с сообщением об успешном завершении нажмите «Закрыть».

До сих пор завершается только операция выборки. Если вы посмотрите на папку репозитория look, она не должна отображать новое изображение, которое я добавил в удаленный репозиторий. Кроме того, demo1.txt не должен отображать последние сделанные изменения.

Последний шаг для завершения операции извлечения — это слияние. Для этого перейдите к опции «Объединить» -> «Локальное объединение» в верхнем меню или нажмите «Ctrl + M».

Должно появиться новое окно с несколькими параметрами, как показано ниже:

Вы можете нажать кнопку «Объединить» или «Визуализировать» изменения перед выполнением объединения.

При нажатии кнопки «Объединить» появляется новое окно, в котором отображается прогресс с сообщением об успешном завершении операции объединения.

Закройте окно и снова перейдите в папку локального репозитория. Там вы должны увидеть недавно добавленные файлы вместе с обновленными изменениями в текстовом файле.

Как добавить команду pull в Git GUI?

Вы можете добавить любую команду в Git GUI, используя меню «Инструменты».

Чтобы добавить команду git pull , перейдите в Инструменты -> Добавить и в следующем появившемся окне введите имя и команду в текстовые поля. Введите там команду pull (с веткой) и введите имя.

Выберите соответствующие опции и нажмите «Добавить». Если вы снова войдете в меню «Инструменты», в меню должна отобразиться добавленная команда, как показано на рисунке выше.

Почему в графическом интерфейсе нет опции прямого извлечения?

Хотя мнения могут расходиться, рекомендуется выполнять выборку + слияние (шаг за шагом), а не операцию извлечения (выборку / слияние вместе).

Выполнение команды fetch позволяет увидеть изменения до внесения фактических изменений в репо.

Команда pull может быть рассмотрена для «опытных пользователей».

В любом случае, если вам удобно использовать команду pull, продолжайте.

Git Pull | Учебник Atlassian Git

Команда git pull используется для извлечения и загрузки содержимого из удаленного репозитория и немедленного обновления локального репозитория в соответствии с этим содержимым. Слияние удаленных исходящих изменений с вашим локальным репозиторием — обычная задача в рабочих процессах совместной работы на основе Git. Команда git pull на самом деле представляет собой комбинацию двух других команд: git fetch , за которым следует git merge .На первом этапе операции git pull выполнит git fetch с областью действия локальной ветки, на которую указывает HEAD . После загрузки содержимого git pull войдет в рабочий процесс слияния. Будет создан новый коммит слияния и обновлен HEAD , чтобы указать на новый коммит.

Использование Git pull

Как это работает

Команда git pull сначала запускает git fetch , который загружает контент из указанного удаленного репозитория.Затем выполняется слияние git для слияния ссылок удаленного содержимого и перехода в новую локальную фиксацию слияния. Чтобы лучше продемонстрировать процесс извлечения и слияния, давайте рассмотрим следующий пример. Предположим, у нас есть репозиторий с главной веткой и удаленным источником.

В этом сценарии команда git pull загрузит все изменения с точки, где локальный и мастер разошлись. В этом примере это точка E. git pull будет извлекать расходящиеся удаленные коммиты, которые являются A-B-C.Затем процесс извлечения создаст новую локальную фиксацию слияния, содержащую содержимое новых удаленных удаленных фиксаций.

На приведенной выше диаграмме мы видим новую фиксацию H. Эта фиксация представляет собой новую фиксацию слиянием, которая содержит содержимое удаленных коммитов A-B-C и имеет объединенное сообщение журнала. Этот пример — одна из немногих стратегий слияния git pull . Параметр --rebase можно передать в git pull , чтобы использовать стратегию слияния rebase вместо коммита слияния.В следующем примере будет продемонстрировано, как работает вытягивание смещения. Предположим, что мы находимся в начальной точке нашей первой диаграммы и выполнили git pull --rebase .

На этой диаграмме мы теперь видим, что извлечение смещения не создает новую фиксацию H. Вместо этого перебазирование скопировало удаленные коммиты A — B — C и переписало локальные коммиты E — F — G, чтобы они появлялись после них в истории локальных / основных фиксаций.

Общие параметры

Извлекает указанную удаленную копию текущей ветви и немедленно объединяет ее с локальной копией.Это то же самое, что git fetch , за которым следует git merge origin / .

  git pull --no-commit <удаленный>  

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

  git pull --rebase <удаленный>  

То же, что и в предыдущем запросе Вместо использования git merge для интеграции удаленной ветки с локальной, используйте git rebase .

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

Обсуждение Git pull

Вы можете думать о git pull как о версии svn update для Git. Это простой способ синхронизировать локальный репозиторий с изменениями, внесенными в исходный код. Следующая диаграмма объясняет каждый этап процесса вытягивания.

Вы начинаете думать, что ваш репозиторий синхронизирован, но затем git fetch показывает, что исходная версия master изменилась с момента последней проверки. Затем git merge немедленно интегрирует удаленный мастер в локальный.

Git извлечение и синхронизация

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

Команду git fetch можно спутать с командой git pull . Оба они используются для загрузки удаленного контента. Важное различие с точки зрения безопасности можно сделать между git pull и get fetch . git fetch можно считать «безопасным» вариантом, тогда как git pull можно считать небезопасным. git fetch загрузит удаленный контент и не изменит состояние локального репозитория. В качестве альтернативы, git pull загрузит удаленный контент и немедленно попытается изменить локальное состояние, чтобы оно соответствовало этому контенту. Это может непреднамеренно привести к переходу локального репозитория в конфликтное состояние.

Вытягивание через Rebase

Параметр --rebase можно использовать для обеспечения линейной истории, предотвращая ненужные коммиты слияния.Многие разработчики предпочитают перебазирование вместо слияния, поскольку это все равно что сказать: «Я хочу, чтобы мои изменения были поверх того, что сделали все». В этом смысле использование git pull с флагом --rebase даже больше похоже на svn update , чем на простой git pull .

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

  git config --global branch.autosetuprebase всегда  

После выполнения этой команды все команды git pull будут интегрированы через git rebase вместо git merge .

Примеры Git Pull

Следующие примеры демонстрируют, как использовать git pull в общих сценариях:

Поведение по умолчанию

Выполнение вызова по умолчанию git pull будет эквивалентно git fetch origin HEAD и git merge HEAD , где HEAD является ссылкой на текущую ветку.

Git pull on пульты

  git checkout new_feature 
git pull <удаленное репо>

В этом примере сначала выполняется проверка и переключается на филиал.После этого выполняется команда git pull с передачей. Это неявно вытянет ветвь newfeature из. После завершения загрузки начнется слияние git .

Git вытягивает перебазирование вместо слияния

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

  git checkout master 
git pull --rebase origin

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

Git Remote | Учебник Atlassian Git

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

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

Пульт Git

Команда git remote позволяет создавать, просматривать и удалять подключения к другим репозиториям. Удаленные подключения больше похожи на закладки, чем на прямые ссылки на другие репозитории. Вместо предоставления доступа в реальном времени к другому репозиторию они служат удобными именами, которые можно использовать для ссылки на не очень удобный URL.

Например, на следующей диаграмме показаны два удаленных подключения из вашего репо к центральному репо и репо другого разработчика.Вместо того, чтобы ссылаться на них по их полным URL-адресам, вы можете передать ярлыки origin и john другим командам Git.

Обзор удаленного использования Git

Команда git remote по сути представляет собой интерфейс для управления списком удаленных записей, которые хранятся в файле ./.git/config репозитория. Следующие команды используются для просмотра текущего состояния удаленного списка.

Просмотр удаленных конфигураций git

Список имеющихся удаленных подключений к другим репозиториям.

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

Создание и изменение удаленных конфигураций git

Команда git remote также является удобным или «вспомогательным» методом для изменения файла ./.git/config репозитория. Представленные ниже команды позволяют управлять подключениями к другим репозиториям. Следующие команды изменят файл репозитория /.git/config . Результат следующих команд также может быть достигнут путем непосредственного редактирования файла ./.git/config файл с текстовым редактором.

  git удаленное добавление <имя>   

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

Удалите соединение с удаленным репозиторием с именем .

  git удаленное переименование <старое имя> <новое имя>  

Переименуйте удаленное соединение с на.

Удаленное обсуждение Git

Git предназначен для предоставления каждому разработчику полностью изолированной среды разработки.Это означает, что информация не передается автоматически между репозиториями. Вместо этого разработчикам необходимо вручную перенести исходящие коммиты в свой локальный репозиторий или вручную отправить свои локальные коммиты обратно в центральный репозиторий. Команда git remote на самом деле просто более простой способ передать URL-адреса этим командам «совместного использования».

Источник Remote

Когда вы клонируете репозиторий с помощью git clone , он автоматически создает удаленное соединение с именем origin, указывающее на клонированный репозиторий.Это полезно для разработчиков, создающих локальную копию центрального репозитория, поскольку это обеспечивает простой способ извлекать изменения из восходящего потока или публиковать локальные коммиты. Это поведение также является причиной того, что большинство проектов на основе Git называют свой центральный репозиторий origin.

URL-адреса репозитория

Git поддерживает множество способов ссылки на удаленный репозиторий. Два самых простых способа доступа к удаленному репо — это протоколы HTTP и SSH. HTTP — это простой способ разрешить анонимный доступ только для чтения к репозиторию.Например:

  http: //host/path/to/repo.git  

Но, как правило, невозможно отправлять коммиты на HTTP-адрес (в любом случае вы не захотите разрешать анонимные push-уведомления). Для доступа для чтения и записи вместо этого следует использовать SSH:

  ssh: //user@host/path/to/repo.git  

Вам понадобится действующая учетная запись SSH на хост-машине, но в остальном Git поддерживает аутентифицированный доступ через SSH из коробки. Современные безопасные сторонние хостинговые решения, такие как Bitbucket.com предоставит вам эти URL-адреса.

Удаленные команды Git

Команда git remote — одна из многих команд Git, которая принимает дополнительные добавленные «подкоманды». Ниже приведен анализ часто используемых подкоманд git remote .

Добавляет запись в ./.git/config для удаленного доступа, названного по URL-адресу репозитория.

Принимает опцию -f , которая будет вызывать git fetch сразу после создания удаленной записи.

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

Обновляет ./.git/config , чтобы переименовать запись в. Все ветки удаленного отслеживания и параметры конфигурации для удаленного обновляются.

Изменяет ./.git/config и удаляет удаленное имя. Все ветви удаленного отслеживания и параметры конфигурации для удаленного устройства удалены.

Выводит URL-адреса для удаленной записи.

Принимает --push , URL-адреса push запрашиваются, а не извлекаются.

При --all будут перечислены все URL-адреса для удаленного устройства.

Выводит высокоуровневую информацию об пульте дистанционного управления.

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

Принимает параметр --dry-run , который перечислит, какие ветки настроены для удаления, но не будет фактически их обрезать.

удаленные примеры Git

Помимо origin, часто бывает удобно иметь соединение с репозиториями ваших товарищей по команде.Например, если ваш коллега, Джон, поддерживает общедоступный репозиторий на dev.example.com/john.git , вы можете добавить соединение следующим образом:

  git удаленное добавление john http://dev.example.com/john.git  

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

Отображение пультов

По умолчанию команда git remote выводит список ранее сохраненных удаленных подключений к другим репозиториям.Это приведет к созданию однострочного вывода, в котором перечислены имена «закладки», имена удаленных репозиториев.

  $ git удаленный 
источник
восходящий поток
other_users_repo

Вызов git remote с опцией -v распечатает список имен репозиториев, отмеченных закладками, и, кроме того, соответствующий URL репозитория. Параметр -v означает «подробный». Ниже приведен пример вывода подробного вывода git remote .

  git remote -v 
origin git @ bitbucket.com: origin_user / reponame.git (выборка)
origin [email protected]: origin_user / reponame.git (push)
восходящий поток https://bitbucket.com/upstream_user/reponame.git (выборка)
восходящий поток https: // bitbucket.com/upstream_user/reponame.git (push)
other_users_repo https://bitbucket.com/other_users_repo/reponame (выборка)
other_users_repo https://bitbucket.com/other_users_repo/reponame (push)

Добавление удаленных репозиториев

Команда git remote add создаст новую запись подключения к удаленному репозиторию.После добавления пульта вы сможете использовать его как удобный ярлык для других команд Git. Дополнительные сведения о принятом синтаксисе URL-адресов см. В разделе «URL-адреса репозитория» ниже. Эта команда создаст новую запись в репозитории ./.git/config . Пример обновления этого файла конфигурации:

  $ git remote add fake_test https://bitbucket.com/upstream_user/reponame.git; [удаленный "remote_test"] 
url = https://bitbucket.com/upstream_user/reponame.git
fetch = + ссылки / головки / *: ссылки / удаленные / удаленный_тест / *

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

Подкоманда show может быть добавлена ​​к git remote для получения подробных выходных данных о конфигурации пульта дистанционного управления. Этот вывод будет содержать список ветвей, связанных с удаленным устройством, а также конечные точки, прикрепленные для выборки и отправки.

  git remote show upstream 
* удаленный upstream
URL-адрес получения: https://bitbucket.com/upstream_user/reponame.git
Push URL: https://bitbucket.com/upstream_user/reponame.git
HEAD ветка: master
Удаленные ветки:
master отслеживается
simd-deprecated отслеживается
учебник отслеживается
Локальный ref настроен для 'git push':
master нажимает на главный (перемотка вперед)

Получение и извлечение с пультов Git

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

Отправка на пульты Git

Команда git push используется для записи в удаленный репозиторий.

  git push <имя-пульта> <имя-ветки>  

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

Переименование и удаление пультов ДУ

  git удаленное переименование <старое имя> <новое имя>  

Команда git remote rename не требует пояснений. При выполнении эта команда переименует удаленное соединение с на. Кроме того, это изменит содержимое ./.git/config , чтобы также переименовать запись для удаленного устройства.

Команда git remote rm удалит соединение с удаленным репозиторием, указанным в параметре.Чтобы продемонстрировать, давайте «отменим» удаленное добавление из нашего последнего примера. Если мы выполним git remote rm remote_test , а затем проверим содержимое ./.git/config , мы увидим, что записи [remote "remote_test"] больше нет.

Manpage Ubuntu: git-pull — загрузка из другого репозитория или локальной ветки и интеграция с ним

Предоставлено: git-man_2.7.4-0ubuntu1_all

 
НАИМЕНОВАНИЕ
       git-pull - извлечь и интегрировать с другим репозиторием или локальной веткой

 
ОБЗОР
         git   pull  [параметры] [<репозиторий> [...]]

 
ОПИСАНИЕ
       Включает изменения из удаленного репозитория в текущую ветку. По умолчанию
       режим git pull - это сокращение от git fetch, за которым следует git merge FETCH_HEAD.

       Точнее,  git   pull  запускает  git   fetch  с заданными параметрами и вызывает  git   merge  to
       объединить полученные заголовки веток с текущей веткой. С --rebase запускается  git 
         rebase  вместо  git   merge . должно быть именем удаленного репозитория, переданным в  git-fetch  (1).
        может назвать произвольную удаленную ссылку (например, имя тега) или даже
       коллекция ссылок с соответствующими ветками удаленного отслеживания (например,
       refs / Heads / *: refs / remotes / origin / *), но обычно это имя ветки в удаленном
       репозиторий.

       Значения по умолчанию для  и  считываются из "удаленного" и "объединенного"
       конфигурация для текущей ветки, заданная параметром  git-branch  (1) --track.origin / master в вашем репозитории

       Затем «git pull» извлечет и воспроизведет изменения из удаленной главной ветки, поскольку она
       отклонился от локального мастера (то есть E) до его текущей фиксации (C) поверх мастера и
       запишите результат в новом коммите вместе с именами двух родительских коммитов и журналом
       сообщение от пользователя с описанием изменений.

                     A --- B --- C происхождение / мастер
                    / \
               D --- E --- F --- G --- H мастер

       Подробнее см.  git-merge  (1), в том числе способ представления и разрешения конфликтов.В Git 1.7.0 или новее для отмены конфликтующего слияния используйте git reset --merge.  Предупреждение : В
       более старые версии Git, использующие  git   pull  с незафиксированными изменениями, не приветствуются: в то время как
       возможно, это оставляет вас в состоянии, из которого может быть трудно выйти в случае
       конфликт.

       Если какое-либо из удаленных изменений перекрывается с локальными незафиксированными изменениями, слияние будет
       автоматически отменяется и дерево работ остается нетронутым. Как правило, лучше всего получить любой местный
       изменения в рабочем состоянии, прежде чем вытащить или спрятать их с помощью  git-stash  (1).
ОПЦИИ
       -q, --quiet
           Это передается как в базовый git-fetch, чтобы подавить отчеты во время передачи,
           и базовый git-merge для подавления вывода во время слияния.

       -v, --verbose
           Передайте --verbose в git-fetch и git-merge.

       - [нет-] рекурсивные подмодули [= да | по запросу | нет]
           Эта опция контролирует, должны ли быть также получены новые коммиты всех заполненных подмодулей
           (см.  git-config  (1) и  gitmodules  (5)).Это может быть необходимо для получения необходимых данных
           для слияния коммитов подмодулей, функция, которую Git изучил в версии 1.7.3. Обратите внимание, что результат
           слияния не будет проверяться в подмодуле, "git submodule update" должен быть
           вызывается впоследствии, чтобы привести дерево работ в соответствие с результатом слияния.

     Опции   связанные   до   объединение 
       --commit, --no-commit
           Выполните слияние и зафиксируйте результат. Эта опция может использоваться для отмены
           - нет фиксации.С --no-commit выполнить слияние, но сделать вид, что слияние не удалось, и не выполнять автоматическую фиксацию,
           чтобы дать пользователю возможность проверить и дополнительно настроить результат слияния, прежде чем
           совершение.

       --edit, -e, --no-edit
           Вызовите редактор перед совершением успешного механического слияния для дальнейшего редактирования
           автоматически сгенерированное сообщение о слиянии, чтобы пользователь мог объяснить и обосновать слияние. В
           Опция --no-edit может использоваться для принятия автоматически сгенерированного сообщения (обычно это
           не рекомендуется).Старые скрипты могут зависеть от исторического поведения, не позволяющего пользователю редактировать
           сообщение журнала слияния. Они увидят открытый редактор, когда запустят git merge. Делать
           такие скрипты проще адаптировать к обновленному поведению, переменная среды
           GIT_MERGE_AUTOEDIT можно установить в значение no в начале их.

       --ff
           Когда слияние разрешается как перемотка вперед, обновляйте только указатель ветки, без
           создание коммита слияния.Это поведение по умолчанию.

       --no-ff
           Создайте фиксацию слияния, даже если слияние разрешается как ускоренная перемотка вперед. Это
           поведение по умолчанию при слиянии аннотированного (и, возможно, подписанного) тега.

       --ff-only
           Отказаться от слияния и выйти с ненулевым статусом, если текущий HEAD уже не
           актуальным или слияние можно решить как перемотку вперед.

       --log [= ], --no-log
           Помимо имен веток, заполните сообщение журнала однострочными описаниями из
           не более  фактических объединяемых коммитов.См. Также  git-fmt-merge-msg  (1).

           С --no-log не выводить однострочные описания фактических сливаемых коммитов.

       --stat, -n, --no-stat
           Показывать diffstat в конце слияния. Diffstat также управляется
           опция конфигурации merge.stat.

           С -n или --no-stat не отображать diffstat в конце слияния.

       --squash, --no-squash
           Создайте рабочее дерево и состояние индекса, как если бы произошло настоящее слияние (за исключением
           информация о слиянии), но на самом деле не совершайте фиксацию, не перемещайте HEAD или не записывайте
           $ GIT_DIR / MERGE_HEAD (чтобы следующая команда git commit создала коммит слияния).Это позволяет вам создать одиночный коммит поверх текущей ветки, чей эффект
           то же, что и слияние другой ветви (или больше в случае осьминога).

           С --no-squash выполните слияние и зафиксируйте результат. Эта опция может быть использована для
           переопределить --squash.

       -s <стратегия>, --strategy = <стратегия>
           Используйте данную стратегию слияния; можно указать более одного раза, чтобы указать их в
           Порядок их надо попробовать. Если нет опции -s, появится встроенный список стратегий.
           вместо этого используется ( git   merge-recursive  при слиянии одной головы,  git   merge-octopus 
           в противном случае).-X <опция>, --strategy-option = <опция>
           Передайте конкретную опцию стратегии слияния в стратегию слияния.

       --verify-подписи, --no-verify-подписи
           Убедитесь, что объединяемые коммиты имеют хорошие и надежные подписи GPG, и отмените операцию.
           слияние, если они этого не сделают.

       --summary, --no-summary
           Синонимы к --stat и --no-stat; они устарели и будут удалены в
           будущее.

       -r, --rebase [= ложь | истина | сохранить]
           Если установлено значение true, после выборки выполняется переустановка текущей ветки поверх восходящей ветки.Если
           есть ветвь удаленного отслеживания, соответствующая восходящей ветке и
           восходящая ветвь была перебазирована с момента последней выборки, перебазирование использует эту информацию для
           Избегайте перенастройки нелокальных изменений.

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

           Если установлено значение false, объединить текущую ветвь с восходящей ветвью.

           См. Pull.rebase, branch.<имя> .rebase и branch.autoSetupRebase в  git-config  (1), если
           вы хотите, чтобы git pull всегда использовал --rebase вместо слияния.

                 Примечание 
               Это потенциально опасный  режим работы . Он переписывает историю, что делает
               не сулит ничего хорошего, если вы уже опубликовали эту историю. Используйте эту опцию для , а не для 
               если вы внимательно не прочитали  git-rebase  (1).

       --no-rebase
           Заменить ранее --rebase. Опции   связанные   до   получение 
       --все
           Получить все пульты.

       -a, --append
           Добавить имена ссылок и имена объектов выбранных ссылок к существующему содержимому
           .git / FETCH_HEAD. Без этой опции старые данные в .git / FETCH_HEAD будут перезаписаны.

       --depth = <глубина>
           Ограничьте выборку указанным количеством коммитов из конца каждой удаленной ветки
           история. При извлечении в мелкий репозиторий  , созданный git clone с --depth = 
           вариант (см.  git-clone  (1)), углубите или сократите историю до указанного количества
           совершает.Теги для углубленных коммитов не извлекаются.

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

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

       --update-мелкий
           По умолчанию при выборке из неглубокого репозитория git fetch отказывается от таких отказов.
           требуют обновления.git / мелкий. Эта опция обновляет .git / shallow и принимает такие ссылки.

       -f, --force
           Когда  git   fetch  используется с :  refspec, он отказывается обновлять
           локальная ветка , если удаленная ветвь , которую она извлекает, не является потомком
           из . Эта опция отменяет эту проверку.

       -k, --keep
           Сохраните скачанный пакет.

       --no-tags
           По умолчанию теги, указывающие на объекты, загруженные из удаленного репозитория
           извлекаются и хранятся локально.Этот параметр отключает автоматическое отслеживание тегов. В
           поведение по умолчанию для пульта дистанционного управления можно указать с помощью параметра remote.  .tagOpt.
           См.  git-config  (1).

       -u, --update-head-ок
           По умолчанию  git   fetch  отказывается обновлять заголовок, соответствующий текущему
           филиал. Этот флаг отключает проверку. Это чисто для внутреннего использования для  git   pull 
           для связи с  git   fetch , и если вы не реализуете свой собственный Porcelain, вы
           не должны его использовать.--upload-pack 
           Когда задано, и репозиторий для выборки обрабатывается  git   fetch-pack ,
             --exec =   передается команде, чтобы указать путь не по умолчанию для
           команда запускается на другом конце.

       --прогресс
           Статус выполнения сообщается в стандартном потоке ошибок по умолчанию, когда он
           прикреплен к терминалу, если не указан -q. Этот флаг заставляет статус прогресса даже
           если стандартный поток ошибок не направлен на терминал.<репозиторий>
           «Удаленный» репозиторий, являющийся источником операции выборки или извлечения. Этот
           Параметр может быть либо URL (см. раздел GIT URLS ниже), либо именем удаленного
           (см. раздел ДИСТАНЦИОННОЕ УПРАВЛЕНИЕ ниже).

       
           Определяет, какие ссылки получать и какие локальные ссылки обновлять. Когда нет  s
           появляются в командной строке, ссылки для выборки читаются с удаленного.  .fetch
           вместо них переменные (см.  git-fetch  (1)).Формат параметра  - необязательный плюс +, за которым следует ссылка на источник.
           , за которым следует двоеточие:, за которым следует ссылка назначения . Толстая кишка может быть
           опускается, если  пуст.

           tag  означает то же, что и refs / tags / : refs / tags / ; он запрашивает выборку
           все до данного тега.

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

                 Примечание 
               Когда известно, что удаленная ветка, которую вы хотите получить, перемотана и переустановлена
               обычно ожидается, что его новый наконечник не будет потомком предыдущего
               подсказка (хранящаяся в ветке удаленного отслеживания при последней загрузке). Вы
               хотел бы использовать знак +, чтобы указать, что необходимы обновления без перемотки вперед
               для таких филиалов.Невозможно определить или заявить, что ветка будет
               стал доступным в репозитории с таким поведением; тянущий пользователь просто должен
               знайте, что это ожидаемый образец использования ветки.

                 Примечание 
               Существует разница между перечислением нескольких  непосредственно на  git   pull 
               командная строка и наличие нескольких записей remote.  .fetch в вашем
               конфигурация для <репозитория> и запуск команды  git   pull  без каких-либо
               явные параметры . явно указаны в командной строке
               всегда объединяются в текущую ветвь после загрузки. Другими словами, если вы
               перечислить более одной удаленной ссылки,  git   pull  создаст слияние Octopus. С другой
               рука, если вы не укажете явный параметр  в командной строке,  git 
                 pull  будет извлекать все , которые он находит в удаленном. .принести
               конфигурации и объединить только первый найденный  в текущую ветку.
               Это связано с тем, что создание Octopus из удаленных ссылок выполняется редко, при этом сохраняя
               отслеживание нескольких удаленных головок за один раз путем получения более чем одной часто
               полезно.

 
GIT URLS
       Как правило, URL-адреса содержат информацию о транспортном протоколе, адресе
       удаленный сервер и путь к репозиторию.В зависимости от транспортного протокола некоторые
       этой информации может отсутствовать.

       Git поддерживает протоколы ssh, git, http и https (кроме того, можно использовать ftp и ftps.
       для получения и rsync можно использовать для получения и отправки, но они неэффективны и
       устарело; не используйте их).

       Собственный транспорт (например, git: // URL) не выполняет аутентификацию и должен использоваться с
       осторожность в незащищенных сетях.

       С ними можно использовать следующие синтаксисы:

       · Ssh: // [пользователь @] хост.xz [: порт] /path/to/repo.git/

       · Git: //host.xz [: порт] /path/to/repo.git/

       · Http [s]: //host.xz [: порт] /path/to/repo.git/

       · Ftp [s]: //host.xz [: порт] /path/to/repo.git/

       · Rsync: //host.xz/path/to/repo.git/

       Альтернативный scp-подобный синтаксис также может использоваться с протоколом ssh:

       · [Пользователь @] host.xz: путь / к / repo.git /

       Этот синтаксис распознается только в том случае, если перед первым двоеточием нет косой черты. Это помогает
       различать локальный путь, содержащий двоеточие.Например, локальный путь foo: bar может
       должен быть указан как абсолютный путь или ./foo:bar, чтобы избежать ошибочной интерпретации как URL-адрес ssh.

       Протоколы ssh и git дополнительно поддерживают расширение имени пользователя:

       · Ssh: // [пользователь @] host.xz [: порт] / ~ [пользователь] /path/to/repo.git/

       · Git: //host.xz [: порт] / ~ [пользователь] /path/to/repo.git/

       · [Пользователь @] host.xz: / ~ [пользователь] /path/to/repo.git/

       Для локальных репозиториев, также изначально поддерживаемых Git, могут использоваться следующие синтаксисы:
       используемый:

       · / Путь / к / репо.git /

       · Файл: ///path/to/repo.git/

       Эти два синтаксиса в основном эквивалентны, за исключением случаев клонирования, когда первое подразумевает
       - местный вариант. Подробнее см.  git-clone  (1).

       Когда Git не знает, как обрабатывать определенный транспортный протокол, он пытается использовать
         remote- <транспорт>  удаленный помощник, если он существует. Чтобы явно запросить удаленного помощника,
       может использоваться следующий синтаксис:

       · <Транспорт> :: <адрес>

       где 
может быть путем, сервером и путем или произвольной URL-подобной строкой распознается конкретным вызываемым удаленным помощником.См. gitremote-helpers (1) для Детали. Если существует большое количество удаленных репозиториев с одинаковыми названиями и вы хотите использовать в другом формате (например, используемые вами URL-адреса будут переписаны в URL-адреса, работа), вы можете создать раздел конфигурации формы: [url "<фактическая база URL>"] вместо этого = <база других URL> Например, вот так: [url "git: //git.host.xz / "] вместо этогоOf = host.xz: / путь / к / вместо этого = работа: URL типа "work: repo.git" или типа "host.xz: /path/to/repo.git" будет переписан в любом контекст, который принимает URL как «git: //git.host.xz/repo.git». Если вы хотите переписать URL-адреса только для push, вы можете создать раздел конфигурации в форма: [url "<фактическая база URL>"] pushInsteadOf = <база других URL> Например, вот так: [url "ssh: // пример.org / "] pushInsteadOf = git: //example.org/ URL типа "git: //example.org/path/to/repo.git" будет заменен на "ssh: //example.org/path/to/repo.git" для push-уведомлений, но при извлечении по-прежнему будет использоваться исходный URL.
ДИСТАНЦИОННОЕ УПРАВЛЕНИЕ
       Вместо URL в качестве аргумента  можно использовать имя одного из следующих:

       · Пульт в файле конфигурации Git: $ GIT_DIR / config,

       · Файл в каталоге $ GIT_DIR / remotes, или

       · Файл в каталоге $ GIT_DIR / branch.Все это также позволяет вам опускать refspec из командной строки, потому что каждый
       содержать refspec, который git будет использовать по умолчанию.

     Именованный   удаленный   в конфигурации     файл 
       Вы можете указать имя пульта дистанционного управления, которое вы ранее настроили с помощью
         git-remote  (1),  git-config  (1) или даже путем ручного редактирования файла $ GIT_DIR / config. URL
       этого пульта дистанционного управления будет использоваться для доступа к репозиторию.Refspec этого пульта дистанционного управления будет
       используется по умолчанию, если вы не указываете refspec в командной строке. Запись в
       config будет выглядеть так:

                   [удаленный "<имя>"]
                           url = 
                           pushurl = 
                           push = 
                           fetch = 

        используется только для пушей. Это необязательно, по умолчанию используется . Именованный   файл   в   $ GIT_DIR / remote 
       Вы можете указать имя файла в $ GIT_DIR / remotes. URL в этом файле
       будет использоваться для доступа к репозиторию. Refspec в этом файле будет использоваться по умолчанию
       когда вы не указываете refspec в командной строке. Этот файл должен иметь следующий
       формат:

                   URL: один из указанных выше форматов URL.
                   Нажать: 
                   Вытяните: 

       Строки push: используются  git   push  и Pull: строки используются  git   pull  и  git   fetch .Для дополнительных сопоставлений ветвей можно указать несколько строк Push: и Pull :.

     Именованный   файл   в   $ GIT_DIR / ветки 
       Вы можете указать имя файла в $ GIT_DIR / branch. URL в этом файле
       будет использоваться для доступа к репозиторию. Этот файл должен иметь следующий формат:

                    # 

        является обязательным; #  не является обязательным.

       В зависимости от операции git будет использовать одну из следующих спецификаций ссылок, если вы не
       укажите его в командной строке.<ветка> - это имя этого файла в $ GIT_DIR / branch
       а  по умолчанию - master.

       git fetch использует:

                   ссылки / главы / <заголовок>: ссылки / головы / <ветка>

       git push использует:

                   ГОЛОВА: ссылки / главы / <заголовок>

 
ОБЪЕДИНЕНИЕ СТРАТЕГИИ
       Механизм слияния (команды git merge и git pull) позволяет бэкэнду  слить   стратегии 
       для выбора с параметром -s.Некоторые стратегии также могут иметь собственные варианты, которые могут быть
       передается путем передачи аргументов -X 
ПО УМОЛЧАНИЮ ПОВЕДЕНИЕ
       Часто люди используют git pull без указания каких-либо параметров. Традиционно это было
       эквивалентно высказыванию git pull origin. Однако, когда конфигурация branch.  .remote
       присутствует в ветке , это значение используется вместо origin.

       Чтобы определить, какой URL использовать для выборки, значение конфигурации
       remote.  .url просматривается, и если такой переменной нет, значение в URL:
       `строка в файле` $ GIT_DIR / remotes /  используется.Чтобы определить, какие удаленные ветки извлекать (и при необходимости хранить в
       удаленного отслеживания ветвей), когда команда запускается без каких-либо параметров refspec на
       в командной строке запрашиваются значения переменной конфигурации remote.  .fetch,
       и если их нет, выполняется обращение к файлу $ GIT_DIR / remotes /  и его `Pull:`
       используются линии. В дополнение к форматам refspec, описанным в разделе ОПЦИИ, вы
       может иметь подстановку refspec, которая выглядит так:

           ссылки / головы / *: ссылки / удаленные / происхождение / *

       У подстановочного refspec должна быть непустая правая часть (т.е.е. должен хранить то, что было доставлено
       ветви удаленного отслеживания), а его LHS и RHS должны заканчиваться на / *. Выше указано, что
       все удаленные ветки отслеживаются с помощью веток удаленного отслеживания в refs / remotes / origin /
       иерархия под тем же именем.

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

       Если в командной строке git pull были указаны явные спецификации refspec, они все объединяются.Если в командной строке не было указано refspec, то git pull использует refspec из
       конфигурация или $ GIT_DIR / remotes / . В таких случаях применяются следующие правила:

        1. Если конфигурация branch.  .merge для текущей ветки  существует, это
           имя филиала на удаленном сайте, который объединяется.

        2. Если refspec является подстановочным, ничего не объединяется.

        3. В противном случае объединяется удаленная ветвь первого refspec.
ПРИМЕРЫ
       · Обновите ветки удаленного отслеживания для репозитория, из которого вы клонировали, а затем объедините одну
           из них в вашу текущую ветку:

               $ git pull, git pull origin

           Обычно объединенная ветка является HEAD удаленного репозитория, но выбор
           определяется параметрами branch.  .remote и branch.  .merge; см.  git- 
             config  (1) для подробностей.· Слить с текущей веткой удаленную ветку следующим образом:

               $ git pull origin дальше

           Это оставляет копию next временно в FETCH_HEAD, но не обновляет никаких
           удаленное отслеживание веток. Используя ветки удаленного отслеживания, то же самое можно сделать с помощью
           вызов выборки и слияния:

               $ git fetch origin
               $ git merge origin / следующий

       Если вы попробовали тянуть, что привело к сложным конфликтам, и хотите начать все сначала, вы
       можно восстановить с помощью  git   reset .
ОШИБКИ
       Использование --recurse-submodules позволяет получать новые коммиты только в уже проверенных подмодулях.
       Сейчас. Когда, например, upstream добавил новый подмодуль в только что выбранные коммиты
       superproject сам подмодуль не может быть извлечен, что делает невозможным извлечение
       этот подмодуль позже без повторной выборки. Ожидается, что это будет исправлено в
       будущая версия Git.

 
СМ. ТАКЖЕ
         git-fetch  (1),  git-merge  (1),  git-config  (1)

 
ГИТ
       Часть пакета  git  (1)
 

Push and Pulling — Документация GitKraken

Толкать и тянуть — ключи к сотрудничеству.🤝


Добавление пультов

Чтобы добавить новый пульт, щелкните значок + при наведении курсора на левую панель, затем введите удаленный URL.

При использовании интеграции, такой как GitHub или Bitbucket, выберите пульты от ваших соавторов в раскрывающемся списке. Это позволяет быстро и легко просматривать другие форки того же репозитория.

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

Вы можете идентифицировать удаленные ветви на графике с помощью следующих значков:

  • — GitHub
  • — Bitbucket
  • — GitLab
  • — Azure DevOps
  • — Другой удаленный сервер

Все удаленные ветки расположены в левой панели.


Толкатель

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

Нажмите текущую извлеченную ветвь, щелкнув Нажмите на главной панели инструментов, или щелкнув правой кнопкой мыши ветку и выбрав.

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

Если удаленная ветвь не может быть переадресована, в отправке будет отказано. Если это так, GitKraken предоставит опцию Pull (перемотка вперед, если возможно) или Force Push.

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

Если отправленная ветка не существует на удаленном компьютере, GitKraken предложит вам назвать и создать новую удаленную ветку. Обычно это имя вилки, за которым следует косая черта, и имя ветки. то есть origin / my-branch .

Перетащите, чтобы нажать

Перетащите ветку на удаленный компьютер, чтобы получить доступ к действию Push .Вы можете перетащить ветку в удаленную ветвь на графике или в удаленную ветку, указанную на левой панели.


Получение

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

Получить все

Fetching получает обновления из удаленных веток, но не обновляет файлы в вашем рабочем каталоге.

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

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

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

Можно быть как впереди, так и за пультом. Однако, если вы и впереди, и позади пульта, вы не сможете выполнить Pull (перемотка вперед, если возможно) , поскольку ветви разошлись.Сначала рассмотрите возможность перенастройки на пульт.

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

Перемотка вперед

Ускоренная перемотка перемещает текущий извлеченный коммит в тот, который был добавлен позже, воспроизводя все коммиты между ними в том порядке, в котором они произошли.

Чтобы перемотать вперед текущую извлеченную фиксацию, вы можете щелкнуть правой кнопкой мыши ветку с более новыми фиксациями и выбрать опцию в меню.


Тянуть

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

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

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

Потяните (перемотайте вперед, если возможно)

Pull (перемотка вперед, если возможно) извлекает любые обновления в удаленной ветви, а затем пытается выполнить перемотку вперед в локальной ветви.Если перемотка вперед невозможна, будет выполнено слияние .

Это вариант по умолчанию для новых пользователей GitKraken.

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

Pull (только перемотка вперед)

Pull (только быстрая перемотка вперед) извлекает все обновления, а затем пытается выполнить перемотку вперед . Если перемотка вперед невозможна, GitKraken не будет вносить никаких изменений в локальное репо.

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

Вытяните (переустановите)

Pull (rebase) сохраняет все коммиты в этой ветке, загружает новые коммиты с пульта дистанционного управления, а затем воспроизводит ваши коммиты. Это дает дополнительное преимущество, заключающееся в том, что все коммиты хранятся в одной строке, в отличие от создания веток, которые затем снова объединяются вместе.

Были втянуты удаленные коммиты, затем поверх них были перемещены локальные коммиты.

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

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

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

Наша страница интерфейса охватывает это и многое другое.


Настройка восходящей ветви

Каждый раз при отправке, извлечении или выборке GitKraken получает обновления из ветки Upstream .

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

Щелкните правой кнопкой мыши ветвь, чтобы настроить восходящий поток, или выберите вариант .

В качестве альтернативы можно перетащить ветвь для отправки вместо настройки восходящего потока.

Git Push and Pull Советы и хитрости

танец толкай!

Отправка по умолчанию

Отправка на удаленный компьютер по умолчанию отправляет в ветку с тем же именем, например

, если вы находитесь в dev ветке

  $ git checkout -b dev 
Переключился на новую ветку 'dev'

И у вас есть эти пульты

  $ git remote 
codebase
origin

Чтобы увидеть, на какие пульты они ссылаются, вы можете добавить флаг -v

Выполнение push здесь приведет к отправке на пульт с той же веткой имя

  $ git push codebase 
Всего 0 (дельта 0), повторно 0 (дельта 0)
удаленный:
удаленный: Чтобы создать запрос на слияние для разработчика, посетите:
удаленный: https: // codebase.your-gitlab.com/infra/cmp_configs_clone/merge_requests/new?merge_request%5Bsource_branch%5D=dev
удаленный:
К https://codebase.your-gitlab.com/infra/cmp_configs_clone.git
* -> dev

Как вы видите, он нажимает на ветку с именем dev , а также на удаленной стороне. Если ветка не существует на удаленной стороне, она будет создана автоматически.

Если вы находитесь в ветке dev локально и пытаетесь нажать на другую ветку, скажем, master , вы получите это сообщение без фактического нажатия

  $ git branch 
* dev
master
customer1 / add-ext- js-packages
customer1 / batch_somefunc
customer1 / desktop-upgrade
customer1 / shrink-somefunc / req / PROJECT-726
customer1 / upgrade-and-add-elastic-desktop
customer2 / local-auth
customer3 / somelib-pipeline- fix
$ git push codebase master
Все в актуальном состоянии

Настройка восходящего потока

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

Синтаксис:

 git push -u   

Обычно вы хотите, чтобы имя вашей ветки на локальном компьютере совпадало с именем ветки на главном сервере

Например:

 git push -u origin feat / new -feature-toggle 

После того, как вы настроите свой апстрим, вам нужно всего лишь сделать

И он автоматически узнает, к какой удаленной ветке он относится. Апстримы выполняются для каждой ветви.

Чтобы иметь возможность проверить, какой восходящий поток вы в настоящее время имеете в виду, запустить:

Обратите внимание, что два флага -v single -v будут выдавать вам только сообщения фиксации, не включая восходящую ветвь.

Отправка в другую ветку

Если вы хотите отправить на тот же удаленный компьютер, но в другую ветку. Используйте следующий синтаксис;

  git push <ветка с новыми изменениями>: <ветка, в которую вы нажимаете>  

Например:

  git push origin dev: master  

Это перемещает локальную ветку dev в origin master branch

Получение из другой ветки

Используется тот же синтаксис для отправки

  git pull origin master: dev  

Это обновляет вашу локальную ветку dev с использованием удаленного источника master branch

Push to a локальный филиал

Проверьте филиалы как удаленные, так и локальные

  $ git branch -av 
* master
customer1 / add-ext-js-packages
customer1 / batch_somefunc
customer1 / desktop-upgrade
customer1 / shrink-somefunc / req / ПРОЕКТ-726

Отправьте изменения с мастера на

.

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

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