90.远程仓库和分支
我们经常需要对远程仓库里的分支进行更新。
当从远程库 clone 时,默认情况下,只会拉取 master
分支,并且会将本地的 master 分支和远程的 master 分支关联起来:
$ git branch
* master
推送本地分支
推送分支,就是把该分支上的所有本地提交推送到远程库。本地新建的分支如果不推送到远程,对其他人就是不可见的。
推送时,要指定本地分支,这样,Git 就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如 dev
,就改成:
$ git push origin dev
实践(先确保工作区是 clean 的):
$ git switch -c remotebranch
Switched to a new branch 'remotebranch'
# 创建一个新的文件夹
$ mkdir 4-remotebranch
$ echo "remote branch" >> ./4-remotebranch/remote.txt
$ git add .
$ git commit -m "add remote.txt"
$ git push gitee remotebranch
然后我们在另一个目录里克隆该项目:
$ git clone git@gitee.com:peterjxl/LearnGit.git
$ ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2023-01-15 12:03 1-diffAndPath
d----- 2023-01-15 12:03 2-versionControl
d----- 2023-01-15 12:03 4-diff
-a---- 2023-01-15 12:03 9 .gitignore
-a---- 2023-01-15 12:03 34 readme.md
可以看到是没有 4-remotebranch 这个文件夹的。
注意:
- origin 和分支名请修改为自己的
- 并不是一定要把所有本地分支往远程推送,这取决于该分支是否要和其他小伙伴合作开发
拉取远程分支
多人协作时,大家都会往 master
和 dev
分支上推送各自的修改。我们一般会定期(比如每天)从分支上拉取最新的代码。
如何查看远程分支上有什么分支呢?可以用 git branch -r
:
$ git branch -r
gitee/feature
gitee/master
github/feature
github/master
如果涉及到多人开发一个分支,但我们从远程仓库 clone 的时候,只有 master 分支;
这时就得拉取远程 origin
的 dev
分支到本地,并关联起来:
$ git switch -c dev origin/dev
这样,我们就可以在 dev
上继续修改,并时不时地把 dev
分支 push
到远程:
$ git add env.txt
$ git commit -m "add env"
$ git push origin dev
而其他开发 dev 分支的小伙伴,则需要定期从 dev 分支拉取更新:
$ git pull
拉取的时候可能会有冲突,需要手动解决,参考前几篇博客。
如果 git pull
提示 no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令 git branch --set-upstream-to <branch-name> origin/<branch-name>
。
实践:我们接着上面的例子来,创建一个分支并关联:
$ git switch -c remotebranch origin/remotebranch
Switched to a new branch 'remotebranch'
branch 'remotebranch' set up to track 'origin/remotebranch'.
$ ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2023-01-15 12:03 2-versionControl
d----- 2023-01-15 12:03 3-branch
d----- 2023-01-15 12:03 4-diff
d----- 2023-01-15 12:03 4-remotebranch
-a---- 2023-01-15 12:03 9 .gitignore
-a---- 2023-01-15 12:03 34 readme.md
此时我们可以看到,当前目录下有 4-remotebranch 这个文件夹了。
注意:在拉取远程分支之前,最好先 git pull 一下。不然可能找不到该分支。
git fetch
git fetch
是将远程主机的最新内容拉到本地仓库
而 git pull
则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge
,这样可能会产生冲突,需要手动解决。
相比之下,git fetch 是一个更安全的选择,因为它从你的远程仓库拉入所有的提交,但不会对你的本地文件做任何修改。你可以在合并前检查哪些文件有变化,哪些文件可能导致冲突。
分支改名
之前我们说过了怎么修改分支名:
$ git branch -m <old_branch_name> <new_branch_name>
但这样是仅能修改本地的分支名的,如果远程仓库上也有该分支,并且想要改名,还需进行以下步骤。
推送这个新分支,从而创建一个新的远程分支:
$ git push origin <new_branch_name>
然后删除远程分支:
$ git push origin -d -f <old_branch_name>
同时推送多个仓库
先前,我们添加了两个远程参考,一个 Gitee,一个 GitHub。如果我们要推送,需要分别推送分支到两个仓库上,有没办法一次性就推送两次呢?有的。
比如,我们想推送到 Gitee 的时候,默认也推送到 GitHub,那么可以给 gitee 添加一个远程的 push 地址,这样一次 push 就能同时 push 到两个地址上面
语法格式:
$ git remote set-url --add 远程仓库名 另一个仓库的push地址
例如:
$ git remote -v
gitee git@gitee.com:peterjxl/LearnGit.git (fetch)
gitee git@gitee.com:peterjxl/LearnGit.git (push)
github git@github.com:Peter-JXL/LearnGit.git (fetch)
github git@github.com:Peter-JXL/LearnGit.git (push)
git remote set-url --add gitee git@github.com:Peter-JXL/LearnGit.git
$ git remote -v //查看是否多了一条push地址
gitee git@gitee.com:peterjxl/LearnGit.git (fetch)
gitee git@gitee.com:peterjxl/LearnGit.git (push)
gitee git@github.com:Peter-JXL/LearnGit.git (push)
github git@github.com:Peter-JXL/LearnGit.git (fetch)
github git@github.com:Peter-JXL/LearnGit.git (push)
至此,我们就可以直接一个 push,同时推送到两个 git 地址。我们来测试下:
$ echo "test push two repository" >> 4-diff/testDiff.txt
$ git add 4-diff/testDiff.txt
$ git commit -m "add test push two repository"
$ git push gitee
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 20 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (12/12), 946 bytes | 946.00 KiB/s, done.
Total 12 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:peterjxl/LearnGit.git
378332f..5ba73a6 master -> master
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 20 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (12/12), 946 bytes | 946.00 KiB/s, done.
Total 12 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 1 local object.
To github.com:Peter-JXL/LearnGit.git
378332f..5ba73a6 master -> master
可以看到 git push 的输出中,既有 Gitee 的输出,也有 GitHub 的输出。
如果不想同时推送多个仓库,可删除 push 地址:
$ git remote set-url --delete origin 地址
以上配置是在 .git/config
文件里存储的。我们也可以通过直接修改该文件来达到配置的效果
原始内容:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "gitee"]
url = git@gitee.com:peterjxl/LearnGit.git
fetch = +refs/heads/*:refs/remotes/gitee/*
[branch "master"]
remote = gitee
merge = refs/heads/master
[remote "github"]
url = git@github.com:Peter-JXL/LearnGit.git
fetch = +refs/heads/*:refs/remotes/github/*
我们在 Gitee 里,添加一行:
url = git@github.com:Peter-JXL/LearnGit.git
修改后:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "gitee"]
url = git@gitee.com:peterjxl/LearnGit.git
fetch = +refs/heads/*:refs/remotes/gitee/*
url = git@github.com:Peter-JXL/LearnGit.git
[branch "master"]
remote = gitee
merge = refs/heads/master
[remote "github"]
url = git@github.com:Peter-JXL/LearnGit.git
fetch = +refs/heads/*:refs/remotes/github/*