Git基本操作
创建Git本地仓库
git init
git clone
配置Git
sh
git config [--global] user.name "Your Name"
git config [--global] user.email "email@example.com"
--global是一个可选项。如果使用了该选项,表示这台机器上所有的Git仓库都会使用这个配置。如果你希望在不同的仓库中使用不同的name和email,那么就不用global这个选项。
查看配置的命令:
sh
git config -l
删除对应的配置的命令为:
sh
git config [--global] --unset user.name
git config [--global] --unset user.email
认识工作区,暂存区,版本库
- 工作区:是指电脑上你要写代码或文件的目录。
- 暂存区 :英文名是stage或者index。一般存放在
.git
目录下的index文件(.git/index
)中,我们把暂存区有时也叫索引(index)。 - 版本库:又叫仓库。工作区有一个隐藏目录,它不算工作区,而是Git的版本库。这个版本库里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都可以追踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以还原。
- 图中左侧为工作区,右侧为版本库。Git的版本库里面存了很多东西,其中最重要的是暂存区。
- 在创建Git版本库的时候,Git会为我们自动创建一个唯一的master分支,以及指向master的一个指针叫做HEAD。
- 当对工作区修改或者新增文件的时候执行
git add
命令,暂存区目录树的文件索引会被更新。 - 当执行提交操作
git commit
的时候,master分支会做相应的更新,可以理解为暂存区的目录树才会真正写到版本库中。
基本命令
git log
:可以使用git log来查看历史提交记录。
如果嫌输出点信息太多,看的眼花缭乱,可以试试加上--pretty=oneline
参数:
需要说明的是,我们看到的⼀⼤串类似 23807c5...56eed6 的是每次提交的 commit id (版本号),Git 的 commit id 不是1,2,3......递增的数字,⽽是⼀个 SHA1 计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰。
查看.git文件
sh
VQ1T7VH07X:git-practice bytedance$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ ├── heads
│ │ └── master
│ └── remotes
│ └── origin
│ └── HEAD
├── objects
│ ├── 68
│ │ └── d4663301d2411e07243ce6ffd05c913541267c
│ ├── 83
│ │ └── b3c1c9e9a278abb737e810dcfe208295660c4f
│ ├── a8
│ │ └── 57e6ed933bee02a6889a95d6189c3ee1405497
│ ├── info
│ └── pack
│ ├── pack-42d887f3aa9c650926611499c530369ad0b83da6.idx
│ └── pack-42d887f3aa9c650926611499c530369ad0b83da6.pack
├── packed-refs
└── refs
├── heads
│ └── master
├── remotes
│ └── origin
│ └── HEAD
└── tags
19 directories, 30 files
-
index就是暂存区,add之后的内容添加到这里
-
HEAD是我们默认指向master分支到指针
默认的master分支其实就是:
打印的这一串哈希值是保存的最新的
commit id
-
object
为Git的对象库,里面包含了创建各种版本库对象以及内容。当执行git add
命令的时候,暂存区的目录树被更新,同时工作区的文件内容被写入到对象库中的一个新的对象中,就位于.git/object
目录下,让我们来看看这些对象有何用处。shVQ1T7VH07X:git-practice bytedance$ ls .git/objects/ 68 83 a8 info pack
查找Object的时候要将
commit id
分成两个部分,其前2位是文件夹名称,后38位是文件名称。找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过sha加密过的文件,好在我们可以使用
git cat-file
命令来查看版本库对象的内容。这个就是我们最近一次的提交。
其中还有一行
tree 83b3c1c9e9a278abb737e810dcfe208295660c4f
,我们使用同样的方式去看看结果:shVQ1T7VH07X:git-practice bytedance$ git cat-file -p 83b3c1c9e9a278abb737e810dcfe208295660c4f 100644 blob a857e6ed933bee02a6889a95d6189c3ee1405497 README.md
我们再看README对应的a857e6ed933bee02a6889a95d6189c3ee1405497:
shVQ1T7VH07X:git-practice bytedance$ git cat-file -p a857e6ed933bee02a6889a95d6189c3ee1405497 # git-practice git实践 我是李鑫阳,我其实很喜欢你
可以看到我们对README做的修改被git记录了下来。
总结
- index: 暂存区, git add 后会更新该内容。
- HEAD: 默认指向 master 分⽀的⼀个指针。
- refs/heads/master: ⽂件⾥保存当前 master 分⽀的最新 commit id 。
- objects: 包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。
修改文件
Git追踪的是修改,而非文件。
我们对README文件做一些修改:
我们可以使用git status
命令来查看在你上次体检之后是否对文件有进行再次修改。
上面的结果告诉我们README被修改过了,但是我们不知道具体哪些地方被修改了。因此使用git diff
命令
然后知道了哪些地方被修改了,我们再去add和commit就放心了。
版本回退
之前我们也提到过,Git 能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现之前前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功了。
执行git reset
命令用于版本回退,可以指定回退某一次提交的版本。回退 本质是要将版本库中的内容进行回退,工作区或者暂存区是否回退要由命令参数决定。
git reset
命令语法格式为: git reset [--soft | --mixed | --hard] [HEAD]
--mixed
为默认选项,使用的时候可以不用带参数。该参数将暂存区 的内容退回为指定提交版本内容,工作区内容保持不变。--soft
参数对于工作区和暂存区 的内容都不变,只是将版本库回退到某个指定版本。--hard
参数将暂存区与工作区都退回到指定版本。切记工作区有未提交到代码时不要用这个命令,因为工作区会回滚,因为工作区会回滚,你没有提交到代码就再也找不到回来了。HEAD
说明:- 可以直接写成commit id,表示指定退回到版本
- HEAD表示当前版本
- HEAD^表示上一个版本
- HEAD^^表示上上个版本
- 以此类推
- 可以使用~数字表示
- HEAD~0表示当前版本
- HEAD~1表示上一个版本
- HEAD~2表示上上个版本
- 以此类推
example
可以看到version1,version2,version3的提交。如果发现version3写的有问题,想回到version2,重新基于version2进行编写。由于我们在这里希望的是将工作区的内容也回退到version2版本。我们这里希望将工作区的内容也回退到version2,因此需要用到--hard参数。
一般情况下到这里就结束了,但是如果我现在后悔了,想再回退到version3怎么办?我们还是可以继续用git reset
命令。但是我们必须要拿到version3的commit id去指定回退的版本。git log
可以找到commit id,但是我们更改了HEAD指向的最新版本之后,git log就已经无法找到version3的commit版本了,这个时候我们需要使用git reflog
命令。这个命令用来记录本地的每一次命令。
这样就可以找到所有的操作记录了,但是2a65701
这是个什么东西呢?这个是version3的commit id
部分。Git版本回退的时候也可以使用部分commit id
来代表目标版本。
这个时候git log也是已经可以看到的了。
可在实际开发中,由于长时间的开发,导致commit id找不到了,但是突然某一天我又想回退到version3,那么该如何操作呢?我告诉你,已经不可能了。
值得说的是,Git 的版本回退速度⾮常快,因为 Git 在内部有个指向当前分⽀(此处是master)的HEAD 指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下⽰意图:
撤销修改
如果我们在工作区写了很长时间的代码,越写越写不下去,觉得自己写的太垃圾了,想恢复到上一个版本
情况一:对于工作区的代码,还没有add
可以使用git checkout -- [file]
命令让工作区的文件回到最近一次add或者commit的状态。
情况二:已经add,但是没有commit
我们回顾一下git reset参数,该命令使用--mixed参数,可以将暂存区的内容退回为指定的版本内容,但工作区文件保持不变。
可以看到暂存区是干净的,工作区有修改。现在相当于没有add了,那么使用git checkout -- [file]
命令就可以了。
情况三:已经add,并且已经commit了
使用git reset --hard HEAD^
,前提是你没有把代码推送到远程仓库,如果你把代码推送到了远程仓库就真的惨了。
删除文件
git rm [file]
可以把文件从暂存区和工作区中删除并且commit。
分支管理
在版本回退里面,每次体检Git都把他们串成一条时间线,这条时间线可以理解成是一个分支。截止到目前为止,只有一条时间线,在Git里面,这个分支叫做主分支,即master分支。
再来理解一下HEAD,HEAD严格来说不是指向体检,而是指向master,master才指向体检,所以HEAD指向的是当前的分支。
每次提交,master分支都会向前移动一步,这样随着你不断的提交,master分支的线也会越来越长,而HEAD只要一直指向master分支即可指出当前分支。
通过查看当前的版本库,我们也可以清晰的理出思路:
sh
VQ1T7VH07X:git-practice bytedance$ cat .git/HEAD
ref: refs/heads/master
VQ1T7VH07X:git-practice bytedance$ cat .git/refs/heads/master
d0b06aae554721d7778698681dd27d05f6417fff
创建分支
发现目前dev和master都指向同一个修改。并可以验证得到HEAD目前是指向master的。
一张图总结:
切换分支
我们发现HEAD已经指向了dev,就表示我们已经成功切换到了dev上面。
接下来,在dev分支下修改README文件,新增一行内容并进行一次提交操作。
这个时候图就成了这个样子了:
合并分支
为了能在master主分支上看到新的提交,就需要将dev分支合并到master分支,实例如下:
git merge
命令用于合并指定分支到当前分支。合并后,master就能看到dev分支提交到内容了。此时的状态如下所示。
Fast- forward代表快进模式,也就是直接把master分支执行dev的当前提交,所以合并速度非常快。当然,也不是每一次合并都能Fast- forward。
删除分支
git branch -d dev
合并冲突
可是,在实际分支合并的时候,并不是想合并就合成功的,有时候可能会遇到代码冲突的问题。
创建一个dev1分支,修改文件内容,然后在master分支上面也修改内容,且修改的位置有冲突。
此时master和dev1的分支有了各自的提交:
此时切换回master分支之后使用git merge dev1
。
这个时候git会告诉你已经冲突了,无法merge,并且会告你的冲突的地方是哪个文件,这个时候打开这个文件,会发现git已经标记出来了冲突的内容:
这个时候需要手动处理冲突。
解决冲突之后此时的状态变成了:
使用git log可以很清楚的看到这个问题。
git log --graph --pretty=oneline --abbrev-commit
分支管理策略
通常合并分支的时候,如果可能,git会使用Fast forward
模式。如果我们使用Fast forward模式,那么形成的合并结果是什么呢?
在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是 merge 进来的还是正常提交的。在这种Fast forward模式下,删除分支之后,查看分支时,会丢掉分支信息,看不出来最新提交到底是merge还是正常提交的。
但是在合并冲突部分,我们看到通过解决分支冲突,我们多了一次commit,最终的状态为:
那么这个就不说fast forward模式了,这样的好处是从分支历史上可以看出分支信息。例如我们现在删除了在合并冲突部分创建的dev1分支,但依旧能看到master其实是由其他分支合并得到的。
Git支持我们强制禁用Fast forward模式。那么就会在merge的时候生成一个新的commit,这样从分支历史上就可以看到分支信息。
git merge --no-ff -m "merge with no-ff" dev2
不使用Fast forward的话是这个样子的。
分支策略
master分支是非常文档的,也就是仅仅用来发布新版本,平时不能在上面干活。
平时在dev分支上面干活,dev分支是不稳定的,到某个时候,例如1.0版本发布的时候,再把dev分支合并到master上面,在master上面发布1.0版本。
因此团队合作的分支看起来其实是这个样子的:
bug分支
假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有 bug,需要解决。在Git中,每个 bug 都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。
可是现在dev2的代码在工作区中开发了一半,还无法提交,怎么办?
例如这样:
Git提供了git stash
命令,可以将当前的工作区信息进行储藏,被储藏的内容可以在将来某个时间恢复出来。
sh
VQ1T7VH07X:git-practice bytedance$ git stash
Saved working directory and index state WIP on dev: 33de037 add
储藏了dev工作区之后,由于我们要给予master分支修复bug,所以需要切回master分支,再新建临时分支来修复。
sh
hyb@139-159-150-152:~/gitcode$ git checkout master # 切回master
Switched to branch 'master'
hyb@139-159-150-152:~/gitcode$ git checkout -b fix_bug # 新建并切换到 fix_bug 分⽀
Switched to a new branch 'fix_bug'
hyb@139-159-150-152:~/gitcode$ vim ReadMe
hyb@139-159-150-152:~/gitcode$ cat ReadMe
hello bit
hello git
hello world
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e # 修复bug--忘记写e
hyb@139-159-150-152:~/gitcode$ git add ReadMe # 重新add,commit
hyb@139-159-150-152:~/gitcode$ git commit -m"fix bug"
[fix_bug 4bbc0c4] fix bug
1 file changed, 1 insertion(+), 1 deletion(-)
修复完成,切换回master分支,并完成合并,最后删除fix_bug分支。
sh
hyb@139-159-150-152:~/gitcode$ git checkout master
Switched to branch 'master'
hyb@139-159-150-152:~/gitcode$ git merge --no-ff -m"merge fix_bug branch" fix_bu
Merge made by the 'recursive' strategy.
ReadMe | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
这个时候回到dev分支,工作区是干净,刚才到工作区去哪里了,用git stash list
进行查看。
使用git stash pop
恢复,恢复的同时会把stash删除。再次查看的时候已经没有现场可以恢复了。
另外,恢复现场也可以采⽤ git stash apply
恢复,但是恢复后,stash内容并不删除,你需要⽤ git stash drop
来删除;你可以多次stash,恢复的时候,先⽤ git stash list
查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}
但我们注意到了,修复 bug 的内容,并没有在 dev2 上显⽰。此时的状态图为:
Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们在 dev2 中当然看不⻅修复 bug 的相关代码。
我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合并即可,但这样其实是有⼀定⻛险的。是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。此时的状态为:
解决这个问题一个好的建议就是:在自己的分支上合并一下master,然后再让master合并dev。这样做的好处是有冲突的时候可以做本地分支解决并且测试,而不影响master。此时的状态为:
sh
VQ1T7VH07X:git-practice bytedance$ git branch
* dev
master
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ git checkout master
M README.md
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 22 commits.
(use "git push" to publish your local commits)
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ git add .
VQ1T7VH07X:git-practice bytedance$ git commit -m "sst"
[master fece00e] sst
1 file changed, 4 insertions(+), 1 deletion(-)
VQ1T7VH07X:git-practice bytedance$ git checkout dev
Switched to branch 'dev'
Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ git add .
VQ1T7VH07X:git-practice bytedance$ git commit -m "aaa"
[dev 5b63b36] aaa
1 file changed, 1 insertion(+), 1 deletion(-)
VQ1T7VH07X:git-practice bytedance$ git merge master
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ git merge --no-ff -m "merge master branch" master
error: Merging is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
VQ1T7VH07X:git-practice bytedance$ git add .
VQ1T7VH07X:git-practice bytedance$ git commit -m "sst"
[dev 6f01b8a] sst
VQ1T7VH07X:git-practice bytedance$ git merge --no-ff -m "merge master branch" master
Already up to date.
VQ1T7VH07X:git-practice bytedance$ git merge master
Already up to date.
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ vim README.md
VQ1T7VH07X:git-practice bytedance$ git add .
VQ1T7VH07X:git-practice bytedance$ git commit -m "lixinyang"
[dev e35cfcf] lixinyang
1 file changed, 1 insertion(+)
VQ1T7VH07X:git-practice bytedance$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 23 commits.
(use "git push" to publish your local commits)
VQ1T7VH07X:git-practice bytedance$ git merge dev
Updating fece00e..e35cfcf
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
远程操作
当我们从远程仓库克隆后,实际上 Git 会⾃动把本地的 master 分⽀和远程的 master 分⽀对应起来,并且,远程仓库的默认名称是 origin 。在本地我们可以使⽤ git remote 命令,来查看远程库的信息,如:
sh
VQ1T7VH07X:git-practice bytedance$ git remote
origin
VQ1T7VH07X:git-practice bytedance$ git remote -v
origin https://github.com/sjmshsh/git-practice.git (fetch)
origin https://github.com/sjmshsh/git-practice.git (push)
向远程仓库推送
sh
git push <远程主机名> <本地分⽀名>:<远程分⽀名>
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号:
git push <远程主机名> <本地分⽀名>
git pull <远程主机名> <远程分⽀名>:<本地分⽀名>
# 如果远程分⽀是与当前分⽀合并,则冒号后⾯的部分可以省略。
git pull <远程主机名> <远程分⽀名>
git pull 和 git fetch的区别
再来看一次git
的工作流程图,如下所示:
可以看到,git fetch
是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中
可以看到,git fetch
是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中
而git pull
则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge
,这样可能会产生冲突,需要手动解决。
在我们本地的git
文件中对应也存储了git
本地仓库分支的commit ID
和 跟踪的远程分支的commit ID
,对应文件如下:
- .git/refs/head/[本地分支]
- .git/refs/remotes/[正在跟踪的分支]
使用 git fetch
更新代码,本地的库中master
的commitID
不变
但是与git
上面关联的那个orign/master
的commit ID
发生改变
这时候我们本地相当于存储了两个代码的版本号,我们还要通过merge
去合并这两个不同的代码版本
也就是fetch
的时候本地的master
没有变化,但是与远程仓关联的那个版本号被更新了,接下来就是在本地merge
合并这两个版本号的代码
相比之下,使用git pull
就更加简单粗暴,会将本地的代码更新至远程仓库里面最新的代码版本,如下图:
一般远端仓库里有新的内容更新,当我们需要把新内容下载的时候,就使用到git pull
或者git fetch
命令
fetch
用法如下:
sh
git fetch <远程主机名> <远程分支名>:<本地分支名>
例如从远程的origin
仓库的master
分支下载代码到本地并新建一个temp
分支
sh
git fetch origin master:temp
如果上述没有冒号,则表示将远程origin
仓库的master
分支拉取下来到本地当前分支
这里git fetch
不会进行合并,执行后需要手动执行git merge
合并,如下:
sh
git merge temp
pull
两者的用法十分相似,pull
用法如下:
sh
git pull <远程主机名> <远程分支名>:<本地分支名>
例如将远程主机origin
的master
分支拉取过来,与本地的branchtest
分支合并,命令如下:
sh
git pull origin master:branchtest
同样如果上述没有冒号,则表示将远程origin
仓库的master
分支拉取下来与本地当前分支合并
区别
相同点:
- 在作用上他们的功能是大致相同的,都是起到了更新代码的作用
不同点:
- git pull是相当于从远程仓库获取最新版本,然后再与本地分支merge,即git pull = git fetch + git merge
- 相比起来,git fetch 更安全也更符合实际要求,在 merge 前,我们可以查看更新情况,根据实际情况再决定是否合并
git本地分支和远程分支建立追踪关系的三种方式
-
手动建立追踪关系
shgit branch --set-upstream-to=<远程主机名>/<远程分支名> <本地分支名>
-
push时建立追踪关系
shgit push -u <远程主机名><本地分支名>
-
新建分支的时候建立追踪关系
shgit checkout -b <本地分支名> <远程主机名>/<远程分支名>
-
查看追踪关系
shgit branch -vv
远程分支
远程引用是对远程仓库的引用,包括分支,标签等等。
- 远程跟踪分支是远程分支状态的引用
- 一旦你进行了网络通信, Git 就会为你移动它们以精确反映远程仓库的状态
- 该分支在远程仓库中的位置就是最后一次连接到它们的位置
命名格式
<remote>/</branch>
为何叫origin?
- git clone 命令会给远程仓库默认命名为 origin,然后拉取它的所有数据, 创建一个指向它的
master
分支的指针,并且在本地将其命名为origin/master【远程分支 origin/master】
- Git 也会给你一个与 origin 的
master
分支在指向同一个地方的本地master
分支,这样你就有工作的基础【本地分支 master】
重点
- origin 和 master 一样,没有特殊的含义
- 只是 git init 时默认的起始分支名字取得就是 master
- 而 git clone 默认给远程仓库名字取得就是 origin
假设指定远程仓库名字
sh
git clone -o lixinyang
那么默认远程分支的名字就是lixinyang/master
克隆之后的远程仓库与本地仓库
- 有人在
git.ourcompany.com
的 master 分支上 push 了新的提交 - 而自己在本地的 master 分支上也做了提交但是没有 push
- 只要本地不拉取最新的数据,那么本地的远程分支(origin/master)还是指向之前的 f4265 节点
本地与远程的工作可以分叉
将本地的远程仓库和服务器上的远程仓库同步数据
sh
git fetch <remote>
git fetch origin
- 这个命令查找origin是哪个服务器(在本例中,它是
git.ourcompany.com
) - 从中拉去本地没有的数据,并且更新本地数据库
- 移动
origin/master
指针到更新之后的位置
可以看到,因为本地的 master 分支已经有过新的提交,所以和 origin/master 远程分支处于分叉状态。
git fetch更新你的远程跟踪分支
现在有个新的 git 服务器位于 git.team1.ourcompany.com
当有多个远程仓库与远程分支的情况下,要怎么添加新的远程仓库引用到本地项目呢?
sh
git remote add <remote> <git 服务器url>
添加另一个远程仓库
抓取新添加的远程仓库在本地没有的数据
sh
git fetch teamone
- 因为那台服务器上现有的数据是
origin
服务器上的一个子集, - 所以 Git 并不会抓取数据而是会设置远程跟踪分支
teamone/master
指向teamone
的master
分支。
推送至远程跟踪分支
sh
git push <remote><branch>
将本地的serverfix分支推送到远程仓库上的awesomebranch分支
sh
git push origin serverfix:awesomebranch
下一次其他协作者从服务器上拉取数据时,他们会在本地生成一个远程分支 origin/serverfix
,指向服务器的 serverfix
分支的引用:
sh
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix
这样操作,本地不会自动新增一个 serverfix 分支,只是有一个不可修改的 origin/serverfix 指针
sh
git merge origin/serverfix
这也是将 origin/serverfix 远程分支下的内容合并到本地当前所在分支
sh
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
这样可以在本地新建一个 serverfix 分支,并且和 origin/serverfix 远程分支指向同一个提交内容