Git精讲

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目录下,让我们来看看这些对象有何用处。

    sh 复制代码
    VQ1T7VH07X:git-practice bytedance$ ls .git/objects/
    68	83	a8	info	pack

    查找Object的时候要将commit id 分成两个部分,其前2位是文件夹名称,后38位是文件名称。

    找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过sha加密过的文件,好在我们可以使用git cat-file 命令来查看版本库对象的内容。

    这个就是我们最近一次的提交。

    其中还有一行tree 83b3c1c9e9a278abb737e810dcfe208295660c4f,我们使用同样的方式去看看结果:

    sh 复制代码
    VQ1T7VH07X:git-practice bytedance$ git cat-file -p 83b3c1c9e9a278abb737e810dcfe208295660c4f
    100644 blob a857e6ed933bee02a6889a95d6189c3ee1405497	README.md

    我们再看README对应的a857e6ed933bee02a6889a95d6189c3ee1405497:

    sh 复制代码
    VQ1T7VH07X:git-practice bytedance$ git cat-file -p a857e6ed933bee02a6889a95d6189c3ee1405497
    # git-practice
    git实践
    我是李鑫阳,我其实很喜欢你

    可以看到我们对README做的修改被git记录了下来。

总结
  1. index: 暂存区, git add 后会更新该内容。
  2. HEAD: 默认指向 master 分⽀的⼀个指针。
  3. refs/heads/master: ⽂件⾥保存当前 master 分⽀的最新 commit id 。
  4. 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更新代码,本地的库中mastercommitID不变

但是与git上面关联的那个orign/mastercommit 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 <远程主机名> <远程分支名>:<本地分支名>

例如将远程主机originmaster分支拉取过来,与本地的branchtest分支合并,命令如下:

sh 复制代码
git pull origin master:branchtest

同样如果上述没有冒号,则表示将远程origin仓库的master分支拉取下来与本地当前分支合并

区别

相同点:

  • 在作用上他们的功能是大致相同的,都是起到了更新代码的作用

不同点:

  • git pull是相当于从远程仓库获取最新版本,然后再与本地分支merge,即git pull = git fetch + git merge
  • 相比起来,git fetch 更安全也更符合实际要求,在 merge 前,我们可以查看更新情况,根据实际情况再决定是否合并

git本地分支和远程分支建立追踪关系的三种方式

  • 手动建立追踪关系

    sh 复制代码
    git branch --set-upstream-to=<远程主机名>/<远程分支名> <本地分支名>
  • push时建立追踪关系

    sh 复制代码
    git push -u <远程主机名><本地分支名>
  • 新建分支的时候建立追踪关系

    sh 复制代码
    git checkout -b <本地分支名> <远程主机名>/<远程分支名>
  • 查看追踪关系

    sh 复制代码
    git 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 指向 teamonemaster 分支。

推送至远程跟踪分支

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 远程分支指向同一个提交内容

相关推荐
SiYuanFeng2 小时前
新手学Git:如何把本地 Git 项目上传到 GitHub
git·github
前端若水3 小时前
git回退并合并分支操作
git
程序员鱼皮9 小时前
Git WorkTree 是什么?凭什么能让 AI 编程效率翻倍?
git·ai·程序员·编程·ai编程
懵逼的小黑子11 小时前
git与远程仓库创建连接
git
前端若水12 小时前
Git 撤销与恢复完全指南(超级详细版)
大数据·git·elasticsearch
golang学习记12 小时前
Git 2.54 来了,这个新命令让我终于敢重写历史了
git·后端
其实防守也摸鱼12 小时前
AWVS下载和安装保姆级教程
linux·服务器·git
前端若水12 小时前
Git 可以做的所有操作(完整分类)
大数据·git·elasticsearch
叹一曲当时只道是寻常12 小时前
Reference 工具安装与使用教程:一条命令管理 Git 仓库引用与知识沉淀
人工智能·git·ai·开源·github
前端若水13 小时前
Git 仓库管理命令完全指南(超级详细版)
大数据·git·elasticsearch