Ответ 1
Оба ответа здесь верны, но я опишу лежащий в основе механизм, потому что, пока я не узнал, что это такое, я нашел полное понятие "отслеживания" совершенно загадочным.
Git разбивает эту "отслеживающую" информацию на две части: имя пульта - обычно слово origin
, как и вы, - и затем имя, которое git на этом удаленном использовании назовите ветвь. 1 Другими словами, если у вас есть вход в систему для удаленного доступа, и вы заходите туда и заходите в репозиторий, вы можете запустить git log master
, чтобы узнать, что было сделано.
Если вы заглянете в свой .git/config
файл, вы увидите, что для каждой локальной ветки, которая "отслеживает" что-то, эти две части. Например, предположим, что у вас есть локальная ветвь с именем experiment
, которую вы настроили для отслеживания origin/master
. Это приведет к:
[branch "experiment"]
remote = origin
merge = master
Но в этом материале отслеживания есть еще одна часть: при запуске git fetch origin
и там что-то новое в ветке master
on origin
, шаг fetch
обновляет локальный origin/master
. Это имя - сначала с именем remote origin
, затем слэшем /
, а затем именем ветки, которое появляется на пульте дистанционного управления, - как вы можете видеть, что произошло на пульте дистанционного управления. После выполнения git fetch
он копирует удаленные имена ветвей (и их соответствующие SHA-1 для своих подсказок ветвления) в ваш локальный репозиторий, переименовывая их с удаленным именем спереди.
На самом деле это шаг git fetch
, который обновляет origin/master
и т.д., и только после этого делает этот "отслеживающий" материал полезным. git теперь может сказать вам, что вы впереди и/или отстаете от некоторого количества коммитов. И теперь вы можете запустить команду, например git log origin/master
, чтобы увидеть, что происходит там - или более интересно, git log --oneline master..origin/master
, чтобы увидеть "свои" фиксации, которых у вас еще нет: по существу, "что принесло извлечение" - и git log --oneline origin/master..master
, чтобы увидеть "ваши", что они еще не сделали. (Если вы уже выполнили слияние или переадресацию, то слишком поздно, чтобы узнать, что принесла ваша выборка, потому что теперь у вас есть то, что у них было тогда, в результате слияния или переадресации.)
Честное слово во всем этом - git pull
. Команда git pull
- это всего лишь короткая строка, которая сначала запускает git fetch
, а затем запускает git merge
(или, если вы перенаправляете ее, git rebase
). Чтобы выполнить эти шаги отдельно, вы запустите git fetch origin
, затем git merge origin/master
или git rebase origin/master
. По историческим причинам 2git pull
берет удаленное имя для ветки, в данном случае master
, а не имя, которое оно переименовывает в ваш репозиторий.
Итак, с этим в качестве фона, давайте посмотрим на некоторые команды:
-
git fetch remote
: Это вообще не требует никаких имен ветвей. Он вызывает данный удаленный доступ, спрашивает его, где находятся все его ветки, и обновляет ваш репозиторий, записывая все эти обновления под именамиorigin/
(чтобы не повлиять на какие-либо из ваших локальных ветвей). Другими словами, это обновляет имена ваших веток, которые могут (или не могут) отслеживаться, но ему не нужно ничего знать о том, что есть или что не отслеживает. -
git status
: Если он говорит, что вы "на ветке X", а ветвьX
отслеживаетorigin/X
,git status
также может сообщить вам, есть ли у васX
которые не находятся наorigin/X
, и наоборот. -
git merge
иgit rebase
: им нужен какой-то способ узнать, что слить, или что нужно переделать. Вы можете назвать это явно, но если вы сообщите git, что ваша веткаX
отслеживаетorigin/X
, тогда всякий раз, когда вы находитесь в веткеX
,git merge
илиgit rebase
, вы узнаете, что делать. -
git branch --set-upstream-to origin/X
: Это основная команда, которая устанавливает или изменяет отслеживание вашей текущей ветки. Другими словами, если вы сейчас находитесь в веткеX
, это обновляетbranch.X.remote
иbranch.X.merge
для вас, так что вам не нужно использовать две отдельные командыgit config
. Вы также можете использоватьgit branch --unset-upstream
для удаления информации отслеживания. -
git push
: если вы не даете ему дополнительной информации, он использует текущую ветвь "remote" - первую половину своей информации отслеживания - чтобы решить, какой удаленный вызов вызывает. Независимо от того, отдаете ли выgit push
удаленное имя или нет, следующая часть зависит от того, укажите ли вы "refspec". Если вы этого не сделаете,git push
используетpush.default
, чтобы решить, какой refspec использовать.
Подождите, что такое refspec?
Вторая простейшая форма refspec - это всего лишь два имени ветки с двоеточием между ними, например master:master
. Для git push
имя слева - это имя вашей ветки, а имя справа - другое имя другой ветки git. Если вы опустите :
, вы получите простейшую форму, в которой имя удаленной стороны, которое будет следовать за :
, выбрано в несколько сложном процессе (описанном в git push
documentation), что фактически зависит от большего количества переменных конфигурации и от того, настроен ли вы вверх.
Как насчет git push -u
? Это просто удобный ярлык: во многом, что git branch --set-upstream-to
является ярлыком для выполнения двух команд git config
, git push -u refspec
является ярлыком для нажатия, а затем делает git branch --set-upstream-to
. Вы должны дать push
refspec для этого, чтобы сделать что-нибудь полезное.
Что делать, если вы даете "половину refspec", например master
? Ну, как указано выше, имя, которое ваш git хочет передать удаленному git, найден сложным процессом, но если вы еще не установили восходящий поток (что довольно вероятно, если вы делаете git push -u
в первую очередь), это будет то же самое, что и ваше местное имя. Таким образом, git push -u origin master
возможно "означает" git push -u origin master:master
, а затем означает git branch --set-upstream-to origin/master
, в конце.
Если вы дадите более полный refspec, например git push -u origin experiment:feature
, это приведет к тому, что ваша ветка experiment
будет origin
, попросив origin
вызвать ее feature
, а затем сделать --set-upstream-to origin/feature
. Обратите внимание, что на данный момент имя вашего локального ветки восходящего потока отличается от локального имени. git в порядке; просто убедитесь, что вы тоже.: -)
Есть более умные трюки, которые git имеет:
-
Если вы запустите
git checkout branch
иbranch
еще не существует, и там одна "очевидная" ветвь удаленного отслеживания, такая какorigin/branch
, git, создаст новый локальныйbranch
который уже отслеживаетorigin/branch
. (То есть локальная ветвь будет иметь свойremote
, установленный вorigin
, а ееmerge
-branch
.) -
Если вы запустите
git branch local-name remote-tracking-name
, git автоматически настроит локальную ветвь для отслеживания соответствующей ветки удаленного отслеживания. (Вы можете настроить git в отношении того, хотите ли вы этого, но по умолчанию.)
Сводка: git fetch
обновляет информацию о том, что использует отслеживание (записи origin/*
, для удаленного origin
). После этого, если это будет сделано с помощью git pull
, который запускает git fetch
3 тогда вы увидите больше информации из таких команд, как git status
; и команды, подобные git rebase
, используют его, чтобы знать, как сделать rebase, без необходимости говорить об этом больше.
Там еще один интересный поворот: любая ветка "вверх по течению" может быть в вашем собственном локальном репозитории. Чтобы получить это, вы установите для remote
для этой ветки значение .
(буквальная точка), а merge
- имя ветки. Вам не обязательно знать, как это сделать, потому что вы можете сделать git branch --set-upstream-to master
, например, чтобы ваша текущая ветка отслеживала ваш собственный master
.
"Входящие" и "исходящие"
Пользователи Mercurial могут задаться вопросом, как вы можете получить эффект hg incoming
или hg outgoing
. Первый говорит вам, что у вас вверх по течению, что у вас нет. Последний говорит вам, что у вас есть, что они этого не делают. Как оказалось, это легко сделать в современном git, потому что git имеет специальный синтаксис @{u}
, чтобы найти текущую ветвь вверх по течению.
Другими словами, если вы находитесь на master
и master
дорожках origin/master
, @{u}
(который вы можете указать как @{upstream}
), это просто еще один способ написать origin/master
. Таким образом, origin/master..master
- это еще один способ написать @{u}..master
. И, если вы находитесь на master
, HEAD
также называет master
, и опускание имени ветки сообщает git использовать HEAD
, поэтому @{u}..
хватает.
Как уже отмечалось выше, после запуска git fetch
на соответствующем пульте дистанционного управления, вы можете использовать git log
, чтобы найти "что у них есть, что у вас нет" и "что у вас есть, что у них нет". Вам нужно запустить этот шаг git fetch
(и не хотите, чтобы в этот момент произошла слияния или переадресации).
Итак:
git config --global alias.incoming '!git fetch && git log --oneline [email protected]{u}'
git config --global alias.outgoing '!git fetch && git log --oneline @{u}..'
(в некоторых оболочках вам может понадобиться \
перед !
или другими трюками цитаты, и может быть проще просто вставить псевдонимы в ваш редактор, запустив git config --global --edit
).
Вы можете, конечно, изменить часть --oneline
на любые параметры, которые вы предпочитаете. (И мне нравится оставить шаг git fetch
для меня, чтобы он вручную запускал себя в любом случае, что упрощает псевдоним только alias.incoming = log --oneline [email protected]{u}
, например. 4 Это в основном просто избегает постоянно приставать вверх по течению.)
1Если вы сохраняете имена своих веток такими же, как и они, вы не сможете увидеть это. Но как только вы начнете использовать ветки сильно, вы, вероятно, столкнетесь с несколькими ветвями, которые все отслеживают один и тот же поток вверх, а затем это действительно имеет значение.
2git pull
фактически предшествует удаленным пулам и ветвям удаленного отслеживания. Из-за этого у него все еще есть все виды странности.
3 Если ваша версия git старше 1.8.4, когда git pull
работает git fetch
, шаг fetch
не обновляет ветки удаленного отслеживания. Это было предназначено как функция, но это была плохая функция, а новые версии версии git. Это означает, однако, что если у вас есть старый git, вы должны быть осторожны с использованием pull
script: это неудобное удобство.
4 Исправлено в редактировании: я случайно написал alias.incoming = git log ...
. Алиасы git считаются другими командами git (например, log
), поэтому вы хотите оставить часть git
, если весь псевдоним не начинается с восклицательного знака !
, и в этом случае целое псевдоним передается в оболочку для запуска. На самом деле я забыл, как сработали псевдонимы, когда все команды были написаны как git-log
, git-branch
, git-fetch
и т.д., Но это, должно быть, было менее сложным...: -)