我正在玩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)我正在使用Mac 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 branch -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相同
答案 0 :(得分:1)
这里的Git术语不是那么好。特别是,根本没有定义术语远程分支和跟踪分支。有关定义,请参见the gitglossary。
人们确实有时会使用短语远程分支来表示远程跟踪分支名称或在远程计算机上检查分支名称的结果< / em>。人们(以及Git书)有时使用短语 tracking branch 来表示具有上游设置的分支。
您的远程跟踪分支定义与Gitglossary中的定义匹配。我不喜欢这个词,因为它导致人们放弃形容词 tracking 并将其称为 remote分支,不同的人对此有不同的解释。 (我更喜欢称其为远程跟踪名称,尽管这并不是真正的改进。主要的改进(如果有的话)在于不再使用“分支”一词。: -))
一个不受上述所有影响的更通用的术语是 ref (这是 reference的缩写; 我倾向于将其大部分时间)。如果您查看Git词汇表,将会看到这一术语定义为:
以
refs/
开头的名称(例如refs/heads/master
)指向对象名称或另一个引用(后者称为符号引用)。为了方便起见,有时在将ref用作Git命令的参数时会缩写它。有关详细信息,请参见gitrevisions [7]。引用存储在存储库中。
无论如何:是的,您可以按照您的建议对名称进行任意修改。 fetch =
中的.git/config
行确定如何修改每个 ref 。
运行git fetch
时,该过程的第一步是您的Git调用其他Git。您的Git到达该Git的URL来自:
git fetch https://github.com/owner/repo.git
,或者hehe_server
,所以存储在git fetch hehe_server
下。
(还有其他几种指定存储库URL的方法,因为在发明遥控器之前有很多历史记录。这是两种常见方法。)
建立连接后,另一个Git就会溢出所有引用。 1 您可以使用git ls-remote
自己观察一下:
git ls-remote hehe_server
此命令的输出是您的Git在他们的Git呈现它们时看到的ref和哈希ID的集合。
无论如何,您的Git现在可以按照fetch =
设置的指示使用这些参考并对其进行操作。每个设置都包含一个 refspec 。引用规范在the git fetch
documentation中进行了描述,但主要由以下内容组成:
+
字符,表示 force ; :
;和源名称或模式与另一个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
。
这意味着要使其正常工作,您必须:
remote.hehe_server.fetch
行,每个分支名称一行,并具有所需的映射:除了它们的master
映射和往常一样,master
映射之外的所有内容。< / li>
每次服务器上的分支名称集更改时,都必须重复此过程。
1 新的有线协议允许在服务器端过滤引用。如果没有这种过滤,具有许多标签和/或分支的存储库可能会在您的Git上进行不必要的对话之前,在您的Git上喷出数兆字节的有害数据。但这会发出所有参考,这是旧协议发生的情况。
答案 1 :(得分:0)
这不是答案。我将测试脚本放在这个答案中,以供其他人了解整个情况。
#!/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