Git:从0掌握Git的使用,满足日常开发需求

本篇内容均参考自《Pro Git》第二版,个人学习笔记(持续更新),仅供参考。原书链接如下: bingohuang.gitbooks.io/progit2/con...

版本控制(VCS)

为何需要

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。 使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。 但额外增加的工作量却微乎其微。

本地版本控制系统

采用本地数据库记录文件历次更新的差异。

集中化版本控制系统(CVCS)

![[Pasted image 20250521143843.png]] 该系统可以让不同系统上的开发者协同开发。可以看到项目的其他开发人员的工作,管理员可管理每个开发者的权限。但是容易产生单点故障。

分布式版本控制系统

分布式版本控制系统解决了单点故障问题。客户端提取的不只是最新版本的文件快照,而是把代码仓库完整地镜像下来,这样任何一处发生故障都可用任意一个镜像出来的本地仓库恢复。

Git基础

记录快照,而非差异

git存储项目文件随时间改变的快照。其他很多版本控制系统都是存储文件的差异,这是git和它们的重要区别。git所记录的数据更像是快照流。

几乎所有操作都是本地执行

  • Git绝大多数操作,都只需要访问本地文件和资源,不需要来自于网络上的其他信息。
  • git在本地库中保存了历史版本的信息,所以不需要再去联网获取历史版本。通过本地获取历史版本的数据就可以计算diff。因此速度也会更快。
  • git在不需要联网或者vpn的时候,就可以进行修改,并提交到本地库。

Git保证完整性

  • git中所有的数据在存储前都会计算校验和,然后以校验和来引用。也就是不可能在git不知情的情况下更改任何文件内容和目录。该功能构建在git底层。

Git一般只添加数据

  • 你执行的 Git 操作,几乎只往 Git 数据库中增加数据。 很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容;但是一旦你提交快照到 Git 中,就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。
  • 这使得我们使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。 更深度探讨 Git 如何保存数据及恢复丢失数据的话题

三种状态

在git的管理下,每个文件都处于三种状态之一:

  • 已提交(committed):安全保存在了本地数据库中。
  • 已修改(modified):修改了文件,但还没保存到数据库。
  • 已暂存(staged):对一个已修改的文件的当前版本做了标记,使之包含在下次提交的快照中。 三个工作区域:
  • git仓库:存放已提交的数据。保存项目的元数据和对象数据库的地方,从其他计算机克隆仓库时,拷贝的就是这里的数据。
  • 工作目录:存放在修改的数据。工作目录是对项目的某个版本独立从git仓库中提取出来的内容,供使用或修改。
  • 暂存区域:存放已暂存的数据。暂存区是一个文件,保存了下次将提交的文件列表信息。一般在git仓库目录中。 git工作流程:
  1. 在工作目录中修改文件。
  2. 暂存文件,将文件的快照放入暂存区域。
  3. 提交更新,找到暂存区域的文件,将快照永久性存储到git仓库目录。

安装

Linux

arduino 复制代码
//ubuntu
sudo yum install git
//debian
sudo apt-get install git

Mac

Windows

配置

安装完git之后,都要先做一些配置。每台计算机上只需要配置一次。git自带git config工具来帮助设置控制git外观和行为的配置变量。

位置

在linux系统中,这些变量存储在三个不同的位置。

  • etc/gitconfig文件:包含系统上每个用户和它们仓库的通用配置,使用带有--system选项的git cofig时,会从此处读写配置变量。
  • /.gitconfig或/.config/git/config文件:只针对当前用户(因为是~)。可以传递==--global选项==让git读写此文件。
  • .git/config文件:当前使用仓库的git目录中的config文件,针对该仓库。 每一级别覆盖上一级别的配置,所以.git/config会覆盖/etc/gitconfig。 .git/config和~/.gitconfig的区别?

用户信息

当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改。

lua 复制代码
git config --global user.name "liufujin"
git config --global user.email liufujin@163.com

--global使得该配置是配置在本用户的配置文件中,也就是~/.gitconfig。 如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。

文本编辑器

既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器,通常是 Vim。 如果你想使用不同的文本编辑器,例如 Emacs,可以这样做:

lua 复制代码
$ git config --global core.editor emacs

检查配置信息

如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。

ini 复制代码
$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...

你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。 通过输入 git config <key>: 来检查 Git 的某一项配置

arduino 复制代码
$ git config user.name
John Doe
shell 复制代码
$ git help <verb>           //使用git时获取帮助
$ git <verb> --help
$ man git-<verb>

$ git help config          //config命令的帮助手册

Git使用

获取Git仓库

该操作时为了创建一个本地仓库。 1.在现有目录中初始化仓库 如果你打算使用 Git 来对现有的项目进行管理,你只需要进入该项目目录并输入:

csharp 复制代码
$ git init

如果你是在一个已经存在文件的文件夹(而不是空文件夹)中初始化 Git 仓库来进行版本控制的话,你应该开始跟踪这些文件并提交. 现在,你已经得到了一个实际维护(或者说跟踪)着若干个文件的git仓库。

2.克隆现有仓库 想要获得一份已经存在了的Git仓库的拷贝,就要用到git clone命令。git clone是克隆的该git仓库服务器上的几乎所有的数据,而不仅仅复制完成工作所需要的文件。

shell 复制代码
$ git clone https://github.com/libgit2/libgit2
  • 格式为 git clone url,默认配置下远程git仓库中的每个文件的每一个版本都将被拉取下来。
  • 以上命令会创建名为libgit2的目录,并在该目录下初始化一个.git文件夹,从远程仓库中拉取的所有数据放入.git文件夹中,然后从中读取最新版本的文件的拷贝。那样我们就可以看到libgit2目录下所有项目文件都有了,而且是最新的,以供后续开发和使用。

更新到git本地仓库

1.文件状态

  • 已跟踪:指被纳入版本控制的文件,在上一次快照中有它们的记录,工作一段时间可能处于未修改、已修改或在暂存区。
  • 未跟踪:工作目录中,除了已跟踪的文件,其他都是未跟踪的文件。它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库,工作目录中所有文件都是已跟踪文件,并处于未修改状态。

2.检查文件状态 git status git status命令会基于当前状态输出各种不同的提示信息。

vbnet 复制代码
```console
$ git status
On branch master
nothing to commit, working directory clean
  • 该信息表明当前处于master分支,所有已跟踪的文件自上次提交后(commit)都未作修改。而且当前目录下,没有出现未跟踪状态的文件。
vbnet 复制代码
$ echo 'My Project' > README
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

nothing added to commit but untracked files present (use "git add" to track)
  • 创建新的文件,出现在untracked files下,该文件是新创建的,未被git跟踪。

3.跟踪新文件 git add

csharp 复制代码
$ git add README
  • 开始跟踪README文件。如果参数不是文件而是目录,则会递归地跟踪该目录下的所有文件。
vbnet 复制代码
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
  • 表明文件已经被跟踪,且Changes to be committed下的文件,都是已经暂存但还未提交的文件。

4.修改文件并暂存 git add

vbnet 复制代码
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md
  • Changes not staged for commit:已修改但还未暂存的文件,这些文件都在工作目录中,需要git add进行暂存。
  • Changes to be committed:已暂存但还未提交的文件,这些文件都在暂存区,需要git commit进行提交。 已跟踪的文件进行修改,则会出现在未暂存的文件中。 已暂存的文件进行修改,则会同时出现在未暂存和未提交的文件列表中。但如果这个时候提交,那么提交的只是已经暂存过的修改。 git add的功能:
  • 开始跟踪新文件。
  • 把已跟踪的文件放到暂存区。
  • 合并时把有冲突的文件标记为已解决状态。 理解为:"添加内容到下一次提交中",而不是"将一个文件添加到项目中"。

5.查看修改(已暂存和未暂存) git diff git diff:

  • 当前做的哪些更新还没有暂存?
  • 有哪些更新已经暂存起来准备好了下次提交? git diff 用来比较工作目录中当前文件暂存区域快照之间的差异,也就是修改之后还没暂存起来的内容。 git diff --staged 查看暂存起来的变化。

6.提交更新 git commit 修改过的但还未暂存的文件,在git commit的时候,并不会被提交,只是保留在本地磁盘中。所以 每次提交之前都要git status看一下是否有未暂存的文件,再去执行git commit git commit时会启动文本编辑器,用来输入本次提交的说明。

sql 复制代码
git commit -m "Fix benchmarks for speed"

通过-m参数,可以直接在命令行中添加本次提交的说明。 提交后显示的信息:

sql 复制代码
$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

7.跳过使用暂存区 每次都要git add才能去git commit会比较繁琐,所以要有方式我们可以直接提交所有的修改。

css 复制代码
git commit -a

这样提交之前就不需要git add了。

8.移除文件、移动文件、忽略文件 要从git中移除某个文件,必须要从跟踪的文件清单中移除,如果只是简单地rm 文件,将只是从工作目录中手工删除文件,该文件还是会出现在未暂存的文件列表中。因此还要git rm 该文件,这样下一次提交时,该文件就不会纳入版本管理了。

在git中对文件改名:

shell 复制代码
$ git mv file_from file_to

忽略文件的话,主要是写.gitignore文件。同时还有glob模式,也就是shell所使用的简化了的正则表达式。

查看提交历史

  • 使用git log命令可以查看提交的历史,该命令还有各式各样的参数,可以控制输出的格式和条目等。
  • git log 默认只能看到你本地仓库中已有的提交。如果你只在本地提交(git commit) ,还没有执行 git pullgit fetch,那你执行 git log 时看到的只是 本地分支的提交记录,不会包含其他协作者的最新提交。
  • 只有当你拉取了远程分支的更新(如通过 git pullgit fetch 后,你的本地仓库才会知道其他协作者的提交,git log 才有可能显示他们的记录。
sql 复制代码
$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit
选项 说明
-p 按补丁格式显示每个更新之间的差异。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,"2 weeks ago")。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
选项 说明
-(n) 仅显示最近的 n 条提交
--since, --after 仅显示指定时间之后的提交。
--until, --before 仅显示指定时间之前的提交。
--author 仅显示指定作者相关的提交。
--committer 仅显示指定提交者相关的提交。
--grep 仅显示含指定关键字的提交
-S 仅显示添加或移除了某个关键字的提交

撤销操作

1.重新提交 git commit --amend 比如提交完了但是漏了几个文件没有添加,可以使用该命令 。它会将暂存区中的文件提交,如果自上次提交以来还未做任何修改,那么快照会保持不变,所修改的只是提交信息。

sql 复制代码
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
  • 最终只会有一次提交,第二次会覆盖第一次的提交。

2.取消暂存的文件

perl 复制代码
git reset HEAD <file>

该操作可以取消暂存区的某个文件,然后将它变为已修改未暂存的文件。

3.撤销对文件的修改 不想保留对某个文件的修改,对它撤销修改并将它还原成上次提交时的样子。

lua 复制代码
git checkout --<file>

远程仓库使用

远程仓库是指托管在因特网或其他网络中的你的项目的版本库,你可以有好几个远程仓库,通常有些仓库对你只读,有些则可以读写。 与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。

1.查看远程仓库 git remote

bash 复制代码
$ git clone https://github.com/schacon/ticgit
Cloning into 'ticgit'...
remote: Reusing existing pack: 1857, done.
remote: Total 1857 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1857/1857), 374.35 KiB | 268.00 KiB/s, done.
Resolving deltas: 100% (772/772), done.
Checking connectivity... done.
$ cd ticgit
$ git remote
origin
  • git remote会列出指定的每一个远程服务器的简写。
  • origin是git给你克隆的仓库服务器的默认名字。
ruby 复制代码
$ git remote -v
origin	https://github.com/schacon/ticgit (fetch)
origin	https://github.com/schacon/ticgit (push)
  • -v显示需要读写远程仓库使用的简写和对应的url。

2.添加远程仓库 git remote add

ruby 复制代码
$ git remote
origin
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
origin	https://github.com/schacon/ticgit (fetch)
origin	https://github.com/schacon/ticgit (push)
pb	https://github.com/paulboone/ticgit (fetch)
pb	https://github.com/paulboone/ticgit (push)
  • 现在可以使用pb来代替整个url,如果想拉取该仓库中有但是本地没有的信息,则git fetch pb

3.从远程仓库抓取和拉取 git fetch 从远程仓库获取数据:

css 复制代码
$ git fetch [remote-name]

该命令访问远程仓库,从中拉取所有本地还没有的数据。

  • 如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 origin为简写。 所以,git fetch origin 会抓取克隆(或上一次抓取)后新推送的所有工作。
  • git fetch 命令会将数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。

4.推送到远程仓库 git push

css 复制代码
git push [remote-name] [branch-name]
$ git push origin master
  • 只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。
  • 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。
  • 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。

5.查看远程仓库 git remote show [remote-name]

sql 复制代码
$ git remote show origin
* remote origin
  Fetch URL: https://github.com/schacon/ticgit
  Push  URL: https://github.com/schacon/ticgit
  HEAD branch: master
  Remote branches:
    master                               tracked
    dev-branch                           tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

6.远程仓库的移除和重命名 重命名引用的名字:

ruby 复制代码
$ git remote rename pb paul
$ git remote
origin
paul

移除:

shell 复制代码
$ git remote rm paul
$ git remote
origin

标签

Git别名

csharp 复制代码
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

Git分支

分支(创建和切换)

1.提交对象 一次提交会包含哪些对象,比如现在有三个文件进行了改动,我们做一次提交commit

  • 暂存操作为每个文件计算校验和,然后把当前版本的文件快照保存到git仓库中。git计算每个子目录的校验和,然后在git仓库中这些校验和保存为树对象。
  • 一个树对象,记录着目录结构和blob索引。
  • 提交对象:包含指向前述树对象的指针和所有提交信息。
  • 首次提交的提交对象没有前向指针,之后每个提交对象,都有指向前一个对象的指针,形成一个快照的链表。

2.分支 git的分支,本质上就是指向提交对象的可变指针,git的默认分支名字是master。多次提交操作之后,你其实已经有一个指向最后那个提交对象的master分支。它会在每次的提交操作中自动向前移动 。

3.分支创建和切换 ==分支的本质就是快照链上的指针!== 创建分支:

复制代码
git branch testing
  • 创建了testing分支,本质上就是创建了一个可移动的指针,

当前分支:

  • 有一个名为HEAD的特殊指针,指向当前所在的本地分支,可以将HEAD想象为当前分支的别名。git branch仅是创建新的分支,但是不会切换到新的分支上。

切换分支:

复制代码
git checkout testing
  • checkout用来切换分支,这样就切换到testing分支上了。
  • 修改文件,并再提交(commit)一次,testing分支会向前移动,master分支却没有变化。
  • git checkout master,切换回master分支。做了两个改变
  • 一是使HEAD指向master分支。
  • 二是将工作目录恢复为master分支所指向的快照内容。
  • 也就是项目会始于一个旧的版本,会改变工作目录中的文件,恢复成该分支最后一次提交时的样子。会忽略testing分支的修改,向另一个方向开发。
  • 如果在master分支上再做一次修改, 则项目的提交历史产生分叉。
  • 我们可以在不同分支间不断地来回切换工作,并在时机成熟时将它们合并起来。
css 复制代码
git log --online --decorate --graph --all

该命令用来查看分叉历史。 branch、checkout、commit是分支管理中非常重要的命令。

分支合并

1.场景:

  • 开发某个网站,为实现某个需求,创建一个新的分支并进行开发,在该分支上展开工作。
  • 有个很严重的问题需要紧急修补。切换到线上分支,为该紧急任务新建一个分支,并在其中修补它。测试通过后,切换到线上分支,并合并这个修补分支,将修改推送到线上分支。
  • 最后切换回最初的工作分支,继续工作。并将该工作也合并到主分支上。

2.新建分支、分支切换

css 复制代码
git checkout -b iss53

-b参数使得我们创建并切换到该分支上。

iss53分支随着我们开发该需求不断前进

突然要修补紧急情况,则:

  • 首先最好要留意iss53中还未提交的修改,使得iss53是个干净的状态。
  • git checkout master 切换到master分支。
  • 对该紧急问题创建hotfix分支,git checkout -b hotfix,并在该分支上对紧急问题进行修复。
  • 可以看到master分支相对于hotfix来说还是在一条线上,没有产生分歧。

3.分支合并 我们在hotfix上修复了问题并且已提交。然后需要把hotfix进行合并:

  • git checkout master 切换到master分支。
  • git merge hotfix,合并hotfix分支的内容到master上。 由于当前master分支所指向的提交是hotfix分支的直接上游,所以Git只是简单地将指针向前移动。(也就是顺着一个分支走下去能达到另一个分支)这种情况叫做"快进"。

接下来回到之前的工作:

  • 首先删除hotfix分支,因为已经合并,并且无用了。-d参数使得我们可以删除分支。

    git branch -d hotfix

  • git checkout iss53 切换回之前工作的分支,并继续进行开发和提交。达到下图中的状态。

分叉的分支的合并:

  • 我们想要把iss53中做的修改合并到master分支中,还是git checkout master,然后git merge iss53。但该合并和之前快进的方式不同,因为产生了分叉。master中有iss53中未有的修改。

  • git会使用两个分支的末端所指的快照(C4和C5),以及这两个分支的工作祖先(C2),做三方的合并。

  • 首先创建创建一个新的快照。(新的提交)

  • 然后将C4与C5相比于C2的修改,都增加到C6中。

  • 让当前的分支指针也就是master指向C6。(本次提交不同之处在于有不止一个父提交)

  • 在合并了分支之后,就可以删除iss53了。

4.有冲突的分支合并 场景:两个不同的分支都对同一个文件的同一处进行了修改,git没法干净地合并它们。 git会暂停下来,等待解决了这个冲突之后再进行合并。

  • 在任意时刻,可以使用git status查看那些因为冲突而未合并的文件。
  • 等解决完了冲突,并且之前有冲突的文件都已经暂存,可以输入git commit来完成合并提交。

分支管理

git branch显示所有的分支,*是当前检出的分支。

markdown 复制代码
$ git branch
  iss53
* master
  testing

-v参数显示所有分支的最近一次提交。

sql 复制代码
$ git branch -v
  iss53   93b412c fix javascript issue
* master  7a98805 Merge branch 'iss53'
  testing 782fd34 add scott to the author list in the readmes

--merged参数显示哪些分支合并进了当前分支,所以iss53可以通过-d参数安全地删掉。

css 复制代码
$ git branch --merged
  iss53
* master

--no-merged参数查看所有包含未合并工作的分支。testing分支还未合并,-d删除它会失败。

css 复制代码
$ git branch --no-merged
  testing

分支开发工作流

1.长期分支 这些分支一般不会删除,而是长期存在。这些不同的长期分支用来标识不同稳定性的分支。当有些工作的稳定性通过了测试,则可以把它合并到更高稳定性的分支中,也就是起到了这种作用。渐进稳定分支的流水线。 master--develop--topic,稳定性依次递减。

2.特性分支 也就是我们针对某一功能或特性的开发去建立新的分支,然后再把该分支的修改的内容合并并且删掉该分支即可,是一种短期存在的分支。 iss91、iss9v2、dumbidea都是一些短期的工作的分支,再完成后就合并成了下面这个样子。其中抛弃了iss91的工作,而保留了iss91v2和dumbidea的工作。

3.注意: 以上所有的分支的开发工作,都是在本地发生的,分支全部存于本地,只发生在本地的git版本库中,没有与服务器发生交互。

远程分支

1.远程引用 远程引用是对远程仓库的引用(指针),包括分支、标签等。

scss 复制代码
git ls-remote(remote)   //显式获取远程引用的完整列表
git remote show(remote) //获得远程分支的更多信息

2.远程跟踪分支 远程跟踪分支是远程分支的状态的引用。它是不能移动的本地引用,远程跟踪分支像是上次连接到远程仓库时,那些分支所处状态的书签。

  • (remote)/(branch) 形式命名。
  • 下图中是git clone时,会克隆远程仓库的所有数据,并且创建一个指向远程master分支的指针,也就是远程跟踪分支origin/master。同时还会创建一个与origin的master指向同一个地方的本地master分支,这是后续本地工作的基础。

3.抓取远程分支git fetch 我在本地master分支上做了一些工作并提交,其他人又推送(push)了自己的提交到远程的master分支。由于不与origin服务器连接,所以origin/master指针不会移动,此时变成了下面这种状态: 如果要同步远程分支中别人的工作,需要运行git fetch origin命令。该命令进行以下工作:

  • 查找origin是哪个远程服务器,从中抓取本地没有的数据。
  • 更新本地数据库,移动origin/master指针指向更新后的位置。 可以看到由于提交的内容不同,所以就产生了分叉。也就是git fetch可以更新远程仓库引用,更新的是远程跟踪分支。

4.多远程仓库和分支的更新 使用git remote add可以增加新的远程仓库引用到当前项目。 如下图,我们又两个远程仓库,其中teamone是origin的子集。

  • 运行git fetch teamone后,可以抓取teamone中有而本地没有的数据,因为是子集,所以不用抓取数据了。直接创建远程跟踪分支teamone/master指向teamone的master分支。

5.推送 git push 当想要公开一个分支的时候,就需要将其推送到有写入权限的远程仓库中。而对于不愿意分享的内容,则放到私人分支上。

perl 复制代码
git push (remote) (branch)
git push origin serverfix
  • 这意味着,推送本地的serverfix分支,来更新远程的serverfix分支。
perl 复制代码
git push origin serverfix:serverfix 
  • 推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支。可以通过这种格式来推送本地分支到一个命名不相同的远程分支。
perl 复制代码
git push origin serverfix:awesomebranch
  • 远程仓库的分支也可以不叫serverfix

下一次其他人从服务器上抓取数据时,就会在本地生成一个远程分支origin/serverfix(远程跟踪分支),指向服务器的serverfix分支的引用。

sql 复制代码
git fetch origin

抓取新的远程跟踪分支时,不是有一个新的serverfix分支,只有一个不可以修改的 origin/serverfix指针。

bash 复制代码
git merge origin/serverfix

对于抓取下来的serverfix,也可把它合并到当前分支。 如果想要在自己的serverfix分支上工作,可以将其建立在远程跟踪分支之上:

bash 复制代码
git checkout -b serverfix origin/serverfix

6.跟踪分支 远程跟踪分支可以使用git fetch去更新。但是从远程跟踪分支也可以签出新的分支,也就是跟踪分支。

bash 复制代码
git checkout -b serverfix origin/serverfix
git checkout -b sf origin/serverfix     //可给本地的跟踪分支创建不同的名字

以上就根据远程跟踪分支origin/serverfix创建了新的跟踪分支serverfix。

  • 跟踪分支是与远程分支有直接关系的本地分支。
  • 在一个跟踪分支上git pull,git能自动识别去哪个服务器上抓取、合并到哪个分支。
  • 克隆一个仓库时,会自动创建一个跟踪origin/master的master分支。
shell 复制代码
$ git checkout --track origin/serverfix
  • 当前分支跟踪远程的serverfix分支。

修改跟踪的分支,-u

vbnet 复制代码
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.

查看设置的所有跟踪分支,-vv

bash 复制代码
$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new
  • 由于本地的分支和远程的分支可能都有更改,所以两者会互相有所不同。比如serverfix跟踪分支的ahead3, behind 1,表示服务器上有一次提交还没有合并到本地,同时本地有三次提交(commit)还没有推送(push)。
  • 上面的testing分支没有跟踪任何远程分支。
  • 以上数组的值,都来自于从每个服务器上最后一次抓取(fetch)的数据,这个命令并没有连接服务器,它只会告诉你关于本地缓存的服务器数据。如果想统计最新的,需要先git fetch --all,然后再git branch -vv

7.拉取 git pull

  • git fetch获取远程数据,但是不会修改工作目录中的内容,只会获取数据让你自己合并。
  • git pull不仅会获取远程数据,还会合并。所以:
ini 复制代码
git pull = git fetch + git merge

8.删除远程分支 如果已经完成了一个特性的开发,并且将远程分支的内容都合并到了远程的master分支中,则可以删除该远程分支。

perl 复制代码
git push origin --delete serverfix

总结:

  • fetch、pull、push都涉及到远程服务器。如果只是在本地,都用不到着几个命令。
  • branch、checkout、add、commit、merge 都只涉及本地仓库。

变基

服务器上的Git

一个远程仓库通常只是一个裸仓库,即一个没有当前工作目录的仓库,因为该仓库仅仅作为合作媒介,不需要从磁碟检查快照,存放的只有git的资料。简单地说,裸仓库就是你专案目录内的.git子目录内容,不包含其他材料。

相关推荐
曾曜8 分钟前
PostgreSQL逻辑复制的原理和实践
后端
豌豆花下猫8 分钟前
Python 潮流周刊#110:JIT 编译器两年回顾,AI 智能体工具大爆发(摘要)
后端·python·ai
轻语呢喃21 分钟前
JavaScript :事件循环机制的深度解析
javascript·后端
ezl1fe23 分钟前
RAG 每日一技(四):让AI读懂你的话,初探RAG的“灵魂”——Embedding
后端
经典199224 分钟前
spring boot 详解以及原理
java·spring boot·后端
Aurora_NeAr26 分钟前
Apache Iceberg数据湖高级特性及性能调优
大数据·后端
程序员清风37 分钟前
程序员要在你能挣钱的时候拼命存钱!
后端·面试·程序员
夜阳朔1 小时前
Conda环境激活失效问题
人工智能·后端·python
白仑色2 小时前
Spring Boot 多环境配置详解
java·spring boot·后端·微服务架构·配置管理
懒斌2 小时前
linux驱动程序
后端