могут ли "удаленная ветвь", "удаленная ветвь отслеживания" и "отслеживающая ветвь" иметь разные имена? - PullRequest
0 голосов
/ 29 апреля 2020

Я играю с git.


Текущий статус:

1) В моем локальном репо есть одна ветка master_local.

2) Пульт ДУ Репо имеет одну ветку master_remote. (имя пульта дистанционного управления - hehe_server)

3) мой локальный .git/config выглядит как

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "hehe_server"]
    url = /path/to/git/remote_main.git
    fetch = +refs/heads/*:refs/remotes/hehe_server/*
[branch "master_local"]
    remote = hehe_server
    merge = refs/heads/master_remote

4) когда я запускаю git fetch, git получит master_remote@hehe_server в hehe_server/master_remote@local (aka, /.git/refs/remotes/hehe_server/master_remote@local)

5) когда я запускаю git branch -vv, он говорит:

* master_local 06022cf [hehe_server/master_remote] my_commit_msg

6) Я понимаю, что

i. master_local@local называется "отслеживающей ветвью"

ii. master_remote@hehe_server называется "удаленная ветвь"

iii. hehe_server/master_remote@local называется «ветвью удаленного отслеживания»

7) Моя git версия git версия 2.23.0.

8) Я использую Ма c 10.15.1


Мой вопрос:

Я хочу переименовать hehe_server/master_remote@local в hehe_server/master_haha@local, сохраняя при этом все остальное тоже самое. Могу ли я это сделать?


Мой эксперимент:

Я пытался играть с линией fetch = внутри .git/config, но это действительно сбивает с толку ...

Тест 1

изменить fetch = +refs/heads/*:refs/remotes/hehe_server/* на fetch = +refs/heads/master_local:refs/remotes/hehe_server/master_remote

Результат 1

git ветвь -vv говорит

* master_local 06022cf my_commit_msg

Кажется, master_local больше не отслеживает master_remote .. Я не понимаю.

Тест 2

изменить fetch = +refs/heads/*:refs/remotes/hehe_server/* на fetch = +refs/heads/master_local:refs/remotes/hehe_server/master_haha

Результат 2

такой же, как результат 1

Ответы [ 2 ]

1 голос
/ 29 апреля 2020
Терминология

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

Люди, однако, иногда используют фразу remote branch , чтобы обозначить либо имя удаленного отслеживания ветви или результат проверки имен филиалов на пульте . Люди - и книга Git - иногда используют фразу отслеживающую ветвь , чтобы обозначить ветвь с восходящим набором .

Ваше определение remote отслеживающая ветка совпадает с таковой в Gitglossary. Мне не нравится этот термин, поскольку он приводит к тому, что люди отбрасывают прилагательное , отслеживающее , и называют его удаленная ветвь , которую разные люди интерпретируют по-разному. (Я предпочитаю называть это именем для удаленного слежения , хотя это не очень большое улучшение. Главное улучшение, если оно есть, заключается в том, чтобы снова не использовать слово «ветвь».: - ))

Более общий термин, который не страдает от всего вышеперечисленного, это ref (что является сокращением от reference; Я склонен излагать его далеко большую часть времени). Если вы посмотрите на глоссарий Git, вы увидите, что он определен как:

Имя, которое начинается с refs/ (например, refs/heads/master), которое указывает на имя объекта или другой ref (последний называется символом c ref). Для удобства ссылка может иногда сокращаться при использовании в качестве аргумента команды Git; см. gitrevisions [7] для деталей. Ссылки хранятся в хранилище.

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

Когда вы запускаете git fetch, первым шагом процесса является то, что ваш Git вызывает какой-то другой Git. URL, по которому ваш Git достигает, что Git происходит из:

  • командной строки, если вы, например, запускаете git fetch https://github.com/owner/repo.git или
  • сохраненный URL-адрес под имя remote , в данном случае это имя, хранящееся в hehe_server, поскольку вы использовали git fetch hehe_server.

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

Установив это соединение, другой Git затем выплескивает все свои ссылки. 1 Вы можете сами убедиться в этом, используя git ls-remote:

git ls-remote hehe_server

Вывод этой команды представляет собой набор ссылок и идентификаторов ha sh, которые ваш Git видит, когда их Git представляет их .

В любом случае, ваш Git может теперь взять эти ссылки и работать с ними, как указано в настройках fetch =. Каждый параметр состоит из refspe c. Refspecs описаны в git fetch документации , но в основном они состоят из:

  • необязательный ведущий + символ, означающий сила ;
  • a источник имя или шаблон;
  • символ двоеточия :; и
  • a имя имя или шаблон.

Имя или шаблон источника сопоставляются с именами, представленными другим Git. Полученное имя или шаблон назначения используется для создания имени, которое ваш Git будет создавать или обновлять (или, с помощью --prune, удалять, если никакое входное имя не соответствует ему).

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

+refs/heads/master:refs/remotes/hehe_server/foo
+refs/heads/master:refs/remotes/hehe_server/bar

заставляет один источник, master, отображать на два выхода, и:

[remote "hehe_server"]
    fetch = +refs/heads/master:refs/remotes/hehe_server/foo
    fetch = +refs/heads/develop:refs/remotes/hehe_server/foo

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

Я хочу переименовать hehe_server/master_remote@local в hehe_server/master_haha@local, оставив все остальное таким же. Могу я это сделать?

Вроде да, но в основном нет. В частности, если вы хотите взять их refs/heads/master и назвать их refs/remotes/hehe_server/master_haha, эта часть проста:

fetch = +refs/heads/master:refs/remotes/hehe_server/master_haha

делает свое дело. Но если вы теперь хотите взять все оставшиеся имена и обработать их обычным способом:

fetch = +refs/heads/*:refs/remotes/origin/*

вы сказали Git, что refs/heads/master должно стать двумя именами локально, поскольку вторая строка отображает имя на refs/remotes/origin/master.

Что это означает, что для того, чтобы это заработало, вы должны:

  • связаться с другим Git
  • получить полный список всех их названий ветвей
  • написать новый набор remote.hehe_server.fetch строк, по одной строке на имя ветви, с желаемым отображением: все, кроме их master отображается как обычно, и их master отображается странно.

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


1 Новый проводной протокол позволяет фильтровать ссылки на сервере. Без этой фильтрации хранилище с большим количеством тегов и / или веток может израсходовать несколько мегабайт нежелательных данных на ваш Git, прежде чем ваш Git сможет начать с ним полезную беседу. Но это - испуская все ссылки - это то, что происходит со старым протоколом.

0 голосов
/ 30 апреля 2020

Это не ответ. Я вставил свой тестовый сценарий в этот ответ, чтобы другие могли получить полную картину.

#!/bin/bash
echo "
change branches' names
    refs/heads/master_local 
    refs/remote/hehe_server/master_haha
    master_remote@remote
"
PATHA=/path/to/an/empty/folder/


# Any subsequent(*) commands which fail will cause the shell script to exit immediately
set -e

# Makes the bash script to print out every command before it is executed except echo
trap '[[ $BASH_COMMAND != echo* ]] && echo "++++++RUN COMMAND: Line ${LINENO}: $BASH_COMMAND --- RESULT IS A BELOW"' DEBUG




cd $PATHA



echo "make a bare repo"
git --git-dir=$PATHA/remote_main.git init --bare


echo "clone"
cd $PATHA
git clone $PATHA/remote_main.git main --origin hehe_server


echo "------------------------------------------------------------------------------------------------------------------------------------"
echo "commit and push in master"
cd $PATHA/main
echo "test@master" > $PATHA/main/index.js
git add .
git commit -m "commit and push in master"
git push


echo "------------------------------------------------------------------------------------------------------------------------------------"
echo "commit and push in feature"
git checkout -b feature
echo "test@feature" > $PATHA/main/index.js
git add .
git commit -m "commit and push in feature"
git push -u hehe_server feature
git checkout master


echo "------------------------------------------------------------------------------------------------------------------------------------"
echo "commit and push in release"
git checkout -b release
echo "test@release" > $PATHA/main/index.js
git add .
git commit -m "commit and push in release"
git push -u hehe_server release
git checkout master



echo "------------------------------------------------------------------------------------------------------------------------------------"
echo "master@local --> master_local, master@hehe_server --> master_remote@hehe_server"

echo "# create and switch to the release branch"
git checkout -b master_local master

echo "# push the master_local branch to the remote and track it"
git push -u hehe_server master_local:master_remote

echo "# delete local master"
git branch -d master

echo "# delete remote master"
git --git-dir=$PATHA/remote_main.git symbolic-ref HEAD refs/heads/master_remote
git push --delete hehe_server master



echo "------------------------------------------------------------------------------------------------------------------------------------"
echo "hehe_server/master_remote@local --> hehe_server/master_haha@local"

echo "remove fetch= section first"
git config --unset remote.hehe_server.fetch
cat .git/config
echo "add first line for fetch="
git config --add remote.hehe_server.fetch "+refs/heads/master_remote:refs/remotes/hehe_server/master_haha"
echo "add second line for fetch="
git config --add remote.hehe_server.fetch "+refs/heads/*:refs/remotes/hehe_server/*"
cat .git/config


echo "check"
echo "see torek's warning: But if you now want to take all the remaining names and handle them in the usual way ...."
git branch -vv  # outputs: * master_local 0870a94 [hehe_server/master_haha: gone] xxx
git fetch
git branch -vv  # outputs: * master_local 0870a94 [hehe_server/master_haha] xxx


echo "why doesn't `git fetch --prune` remove the hehe_server/master_remote@local?"
ls -lah $PATHA/main/.git/refs/remotes/hehe_server
git fetch --prune
ls -lah $PATHA/main/.git/refs/remotes/hehe_server
...