Git精讲

Git基本操作

创建Git本地仓库

  • git init
  • git clone

配置Git

git config [--global] user.name "Your Name"
git config [--global] user.email "[email protected]"

–global是一个可选项。如果使用了该选项,表示这台机器上所有的Git仓库都会使用这个配置。如果你希望在不同的仓库中使用不同的name和email,那么就不用global这个选项。

查看配置的命令:

git config -l

删除对应的配置的命令为:

git config [--global] --unset user.name
git config [--global] --unset user.email

认识工作区,暂存区,版本库

  • 工作区:是指电脑上你要写代码或文件的目录。
  • 暂存区:英文名是stage或者index。一般存放在.git目录下的index文件(.git/index)中,我们把暂存区有时也叫索引(index)。
  • 版本库:又叫仓库。工作区有一个隐藏目录,它不算工作区,而是Git的版本库。这个版本库里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都可以追踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以还原。

Git精讲_第1张图片

  • 图中左侧为工作区,右侧为版本库。Git的版本库里面存了很多东西,其中最重要的是暂存区。
  • 在创建Git版本库的时候,Git会为我们自动创建一个唯一的master分支,以及指向master的一个指针叫做HEAD。
  • 当对工作区修改或者新增文件的时候执行git add命令,暂存区目录树的文件索引会被更新。
  • 当执行提交操作git commit的时候,master分支会做相应的更新,可以理解为暂存区的目录树才会真正写到版本库中。

基本命令

git log:可以使用git log来查看历史提交记录。
Git精讲_第2张图片

如果嫌输出点信息太多,看的眼花缭乱,可以试试加上--pretty=oneline参数:

在这里插入图片描述

需要说明的是,我们看到的⼀⼤串类似 23807c5…56eed6 的是每次提交的 commit id (版本号),Git 的 commit id 不是1,2,3……递增的数字,⽽是⼀个 SHA1 计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰。

查看.git文件

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分支其实就是:

    Git精讲_第3张图片

    打印的这一串哈希值是保存的最新的commit id

  • object为Git的对象库,里面包含了创建各种版本库对象以及内容。当执行git add命令的时候,暂存区的目录树被更新,同时工作区的文件内容被写入到对象库中的一个新的对象中,就位于.git/object目录下,让我们来看看这些对象有何用处。

    VQ1T7VH07X:git-practice bytedance$ ls .git/objects/
    68	83	a8	info	pack
    

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

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

    Git精讲_第4张图片

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

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

    VQ1T7VH07X:git-practice bytedance$ git cat-file -p 83b3c1c9e9a278abb737e810dcfe208295660c4f
    100644 blob a857e6ed933bee02a6889a95d6189c3ee1405497	README.md
    

    我们再看README对应的a857e6ed933bee02a6889a95d6189c3ee1405497:

    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精讲_第5张图片

我们可以使用git status 命令来查看在你上次体检之后是否对文件有进行再次修改。

Git精讲_第6张图片

上面的结果告诉我们README被修改过了,但是我们不知道具体哪些地方被修改了。因此使用git diff命令

Git精讲_第7张图片

然后知道了哪些地方被修改了,我们再去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

Git精讲_第8张图片

可以看到version1,version2,version3的提交。如果发现version3写的有问题,想回到version2,重新基于version2进行编写。由于我们在这里希望的是将工作区的内容也回退到version2版本。我们这里希望将工作区的内容也回退到version2,因此需要用到–hard参数。

Git精讲_第9张图片

一般情况下到这里就结束了,但是如果我现在后悔了,想再回退到version3怎么办?我们还是可以继续用git reset命令。但是我们必须要拿到version3的commit id去指定回退的版本。git log可以找到commit id,但是我们更改了HEAD指向的最新版本之后,git log就已经无法找到version3的commit版本了,这个时候我们需要使用git reflog命令。这个命令用来记录本地的每一次命令。

Git精讲_第10张图片

这样就可以找到所有的操作记录了,但是2a65701这是个什么东西呢?这个是version3的commit id部分。Git版本回退的时候也可以使用部分commit id来代表目标版本。

Git精讲_第11张图片

这个时候git log也是已经可以看到的了。

可在实际开发中,由于长时间的开发,导致commit id找不到了,但是突然某一天我又想回退到version3,那么该如何操作呢?我告诉你,已经不可能了

值得说的是,Git 的版本回退速度⾮常快,因为 Git 在内部有个指向当前分⽀(此处是master)的HEAD 指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下⽰意图:

Git精讲_第12张图片

撤销修改

如果我们在工作区写了很长时间的代码,越写越写不下去,觉得自己写的太垃圾了,想恢复到上一个版本

情况一:对于工作区的代码,还没有add

可以使用git checkout -- [file]命令让工作区的文件回到最近一次add或者commit的状态。

Git精讲_第13张图片

情况二:已经add,但是没有commit

Git精讲_第14张图片

我们回顾一下git reset参数,该命令使用–mixed参数,可以将暂存区的内容退回为指定的版本内容,但工作区文件保持不变。

Git精讲_第15张图片

可以看到暂存区是干净的,工作区有修改。现在相当于没有add了,那么使用git checkout -- [file]命令就可以了。

Git精讲_第16张图片

情况三:已经add,并且已经commit了

使用git reset --hard HEAD^,前提是你没有把代码推送到远程仓库,如果你把代码推送到了远程仓库就真的惨了。

删除文件

git rm [file]可以把文件从暂存区和工作区中删除并且commit。

分支管理

在版本回退里面,每次体检Git都把他们串成一条时间线,这条时间线可以理解成是一个分支。截止到目前为止,只有一条时间线,在Git里面,这个分支叫做主分支,即master分支。

Git精讲_第17张图片

再来理解一下HEAD,HEAD严格来说不是指向体检,而是指向master,master才指向体检,所以HEAD指向的是当前的分支。

每次提交,master分支都会向前移动一步,这样随着你不断的提交,master分支的线也会越来越长,而HEAD只要一直指向master分支即可指出当前分支。

通过查看当前的版本库,我们也可以清晰的理出思路:

VQ1T7VH07X:git-practice bytedance$ cat .git/HEAD
ref: refs/heads/master
VQ1T7VH07X:git-practice bytedance$ cat .git/refs/heads/master
d0b06aae554721d7778698681dd27d05f6417fff

创建分支

Git精讲_第18张图片

发现目前dev和master都指向同一个修改。并可以验证得到HEAD目前是指向master的。

一张图总结:

Git精讲_第19张图片

切换分支

Git精讲_第20张图片

我们发现HEAD已经指向了dev,就表示我们已经成功切换到了dev上面。

接下来,在dev分支下修改README文件,新增一行内容并进行一次提交操作。

这个时候图就成了这个样子了:

Git精讲_第21张图片

合并分支

为了能在master主分支上看到新的提交,就需要将dev分支合并到master分支,实例如下:

Git精讲_第22张图片

git merge命令用于合并指定分支到当前分支。合并后,master就能看到dev分支提交到内容了。此时的状态如下所示。

Git精讲_第23张图片

Fast- forward代表快进模式,也就是直接把master分支执行dev的当前提交,所以合并速度非常快。当然,也不是每一次合并都能Fast- forward。

删除分支

git branch -d dev

Git精讲_第24张图片

合并冲突

可是,在实际分支合并的时候,并不是想合并就合成功的,有时候可能会遇到代码冲突的问题。

创建一个dev1分支,修改文件内容,然后在master分支上面也修改内容,且修改的位置有冲突。

此时master和dev1的分支有了各自的提交:

Git精讲_第25张图片

此时切换回master分支之后使用git merge dev1

这个时候git会告诉你已经冲突了,无法merge,并且会告你的冲突的地方是哪个文件,这个时候打开这个文件,会发现git已经标记出来了冲突的内容:

Git精讲_第26张图片

这个时候需要手动处理冲突。

解决冲突之后此时的状态变成了:

Git精讲_第27张图片

使用git log可以很清楚的看到这个问题。

Git精讲_第28张图片

git log --graph --pretty=oneline --abbrev-commit

分支管理策略

通常合并分支的时候,如果可能,git会使用Fast forward模式。如果我们使用Fast forward模式,那么形成的合并结果是什么呢?

Git精讲_第29张图片

在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是 merge 进来的还是正常提交的。在这种Fast forward模式下,删除分支之后,查看分支时,会丢掉分支信息,看不出来最新提交到底是merge还是正常提交的。

但是在合并冲突部分,我们看到通过解决分支冲突,我们多了一次commit,最终的状态为:

Git精讲_第30张图片

那么这个就不说fast forward模式了,这样的好处是从分支历史上可以看出分支信息。例如我们现在删除了在合并冲突部分创建的dev1分支,但依旧能看到master其实是由其他分支合并得到的。

Git支持我们强制禁用Fast forward模式。那么就会在merge的时候生成一个新的commit,这样从分支历史上就可以看到分支信息。

git merge --no-ff -m "merge with no-ff" dev2

Git精讲_第31张图片

不使用Fast forward的话是这个样子的。

Git精讲_第32张图片

分支策略

master分支是非常文档的,也就是仅仅用来发布新版本,平时不能在上面干活。

平时在dev分支上面干活,dev分支是不稳定的,到某个时候,例如1.0版本发布的时候,再把dev分支合并到master上面,在master上面发布1.0版本。

因此团队合作的分支看起来其实是这个样子的:

Git精讲_第33张图片

bug分支

假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有 bug,需要解决。在Git中,每个 bug 都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。

可是现在dev2的代码在工作区中开发了一半,还无法提交,怎么办?

例如这样:

Git精讲_第34张图片

Git提供了git stash命令,可以将当前的工作区信息进行储藏,被储藏的内容可以在将来某个时间恢复出来。

VQ1T7VH07X:git-practice bytedance$ git stash
Saved working directory and index state WIP on dev: 33de037 add

储藏了dev工作区之后,由于我们要给予master分支修复bug,所以需要切回master分支,再新建临时分支来修复。

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分支。

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精讲_第35张图片

使用git stash pop恢复,恢复的同时会把stash删除。再次查看的时候已经没有现场可以恢复了。

另外,恢复现场也可以采⽤ git stash apply 恢复,但是恢复后,stash内容并不删除,你需要⽤ git stash drop 来删除;你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}

但我们注意到了,修复 bug 的内容,并没有在 dev2 上显⽰。此时的状态图为:

Git精讲_第36张图片

Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们在 dev2 中当然看不⻅修复 bug 的相关代码。

我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合并即可,但这样其实是有⼀定⻛险的。是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。此时的状态为:

Git精讲_第37张图片

解决这个问题一个好的建议就是:在自己的分支上合并一下master,然后再让master合并dev。这样做的好处是有冲突的时候可以做本地分支解决并且测试,而不影响master。此时的状态为:

Git精讲_第38张图片

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 '
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 命令,来查看远程库的信息,如:

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)

向远程仓库推送

git push <远程主机名> <本地分⽀名>:<远程分⽀名>
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号:
git push <远程主机名> <本地分⽀名>


git pull <远程主机名> <远程分⽀名>:<本地分⽀名>
# 如果远程分⽀是与当前分⽀合并,则冒号后⾯的部分可以省略。
git pull <远程主机名> <远程分⽀名>

git pull 和 git fetch的区别

再来看一次git的工作流程图,如下所示:

Git精讲_第39张图片

可以看到,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去合并这两个不同的代码版本

Git精讲_第40张图片

也就是fetch的时候本地的master没有变化,但是与远程仓关联的那个版本号被更新了,接下来就是在本地merge合并这两个版本号的代码

相比之下,使用git pull就更加简单粗暴,会将本地的代码更新至远程仓库里面最新的代码版本,如下图:

Git精讲_第41张图片

一般远端仓库里有新的内容更新,当我们需要把新内容下载的时候,就使用到git pull或者git fetch命令

fetch

用法如下:

git fetch <远程主机名> <远程分支名>:<本地分支名>

例如从远程的origin仓库的master分支下载代码到本地并新建一个temp分支

git fetch origin master:temp

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

这里git fetch不会进行合并,执行后需要手动执行git merge合并,如下:

git merge temp

pull

两者的用法十分相似,pull用法如下:

git pull <远程主机名> <远程分支名>:<本地分支名>

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

git pull origin master:branchtest

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

区别

相同点:

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

不同点:

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

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

  • 手动建立追踪关系

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

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

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

    git branch -vv
    

远程分支

远程引用是对远程仓库的引用,包括分支,标签等等。

  • 远程跟踪分支是远程分支状态的引用
  • 一旦你进行了网络通信, Git 就会为你移动它们以精确反映远程仓库的状态
  • 该分支在远程仓库中的位置就是最后一次连接到它们的位置

命名格式

/

为何叫origin?

  • git clone 命令会给远程仓库默认命名为 origin,然后拉取它的所有数据, 创建一个指向它的 master 分支的指针,并且在本地将其命名为 origin/master【远程分支 origin/master】
  • Git 也会给你一个与 origin 的 master 分支在指向同一个地方的本地 master 分支,这样你就有工作的基础【本地分支 master】
重点
  • origin 和 master 一样,没有特殊的含义
  • 只是 git init 时默认的起始分支名字取得就是 master
  • 而 git clone 默认给远程仓库名字取得就是 origin

假设指定远程仓库名字

git clone -o lixinyang

那么默认远程分支的名字就是lixinyang/master

Git精讲_第42张图片

克隆之后的远程仓库与本地仓库

  • 有人在 git.ourcompany.com 的 master 分支上 push 了新的提交
  • 而自己在本地的 master 分支上也做了提交但是没有 push
  • 只要本地不拉取最新的数据,那么本地的远程分支(origin/master)还是指向之前的 f4265 节点

Git精讲_第43张图片

本地与远程的工作可以分叉

将本地的远程仓库和服务器上的远程仓库同步数据

git fetch <remote>
git fetch origin
  • 这个命令查找origin是哪个服务器(在本例中,它是 git.ourcompany.com
  • 从中拉去本地没有的数据,并且更新本地数据库
  • 移动origin/master指针到更新之后的位置

Git精讲_第44张图片

可以看到,因为本地的 master 分支已经有过新的提交,所以和 origin/master 远程分支处于分叉状态。

git fetch更新你的远程跟踪分支

现在有个新的 git 服务器位于 git.team1.ourcompany.com

当有多个远程仓库与远程分支的情况下,要怎么添加新的远程仓库引用到本地项目呢?

git remote add <remote> <git 服务器url>

Git精讲_第45张图片

添加另一个远程仓库

抓取新添加的远程仓库在本地没有的数据

git fetch teamone
  • 因为那台服务器上现有的数据是 origin 服务器上的一个子集,
  • 所以 Git 并不会抓取数据而是会设置远程跟踪分支 teamone/master 指向 teamonemaster 分支。

Git精讲_第46张图片

推送至远程跟踪分支

git push <remote><branch>

将本地的serverfix分支推送到远程仓库上的awesomebranch分支

git push origin serverfix:awesomebranch

下一次其他协作者从服务器上拉取数据时,他们会在本地生成一个远程分支 origin/serverfix,指向服务器的 serverfix 分支的引用:

$ 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 指针

git merge origin/serverfix 

这也是将 origin/serverfix 远程分支下的内容合并到本地当前所在分支

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

你可能感兴趣的:(工作中遇到的问题,git)