Git 学习笔记

Git学习

一、Git基础学习

1. Git常用命令

命令说明
安装与配置
sudo apt-get install gitUbuntu 上安装 Git 命令
git config --global user.name 用户名设置用户签名
(安装 Git 后务必设置)
git config --global user.email email 地址设置用户 email 地址
(安装 Git 后务必设置)
获取与创建项目
git init初始化本地库
git clone 远程库地址从远程库克隆到本地
基本快照
git status查看本地库状态
git add 文件名添加变动文件到暂存区
git add .添加当前目录下所有变动文件到暂存区
git restore --staged 文件名复位在暂存区的文件(add 反悔药)
git rm --cached 文件名移除在暂存区的文件(add 反悔药)(同上一条)
git commit -m “备注文本” 文件名提交暂存区文件到本地库
(文件名缺省时,将暂存区所有文件提交)
git commit --amend修改上次提交的备注文本
git revert 版本号 (7 位)撤销指定的提交(commit 反悔药)(慎用)
git reset --hard 版本号 (7 位)版本间穿梭(配合 git reflog 使用)
git reset --hard HEAD^穿梭到上一个版本
分支与合并
git branch列出所有分支
git branch 分支名创建分支
git checkout 分支名切换分支
git merge 分支名 B分支 B 合并到 A
(A 为当前工作目录所处分支)
git branch -d 分支名删除分支
git tag列出所有本地标签
git tag -l 通配模式文本 (*)根据符合通配模式文本,列出所有本地标签
git tag 标签名为最新提交创建轻量标签
git tag 标签名 版本号 (7 位)为对应版本号提交创建轻量标签(在后期打标签)
git tag -a 标签名 -m 备注文本为最新提交创建附注标签
git tag -d 标签名删除指定标签
共享与更新项目
git remote add 别名 远程仓库地址添加远程库
git remote -v查看添加过的远程库
git push 远程库地址或其别名 分支名推送到远程库
git push 远程库地址或其别名 --tags推送所有标签到远程库
git fetch将远程库的最新内容拉到本地
git pull 远程库地址或其别名 分支名将远程仓库对于分支最新内容拉下来后与当前本地分支直接合并,
相当于 git fetch + git merge,这样可能会产生冲突,需要手动解决
检查与比较
git show 标签名显示标签信息和与之对应的提交信息
git show 版本号 (7 位)显示对应版本对应的提交信息
git log显示当前分支所有提交过的版本信息
git log --follow 文件名显示当前分支所有提交过的关于指定文件版本信息
git log --pretty=oneline显示当前分支所有提交过的版本信息(精简)
git log --graph显示当前分支所有提交过的版本信息(附有分支合并图)
git diff 分支一 分支二显示两分支差异
git diff 版本号一 (7 位) 版本号二 (7 位)显示同一分支两版本差异
管理
git reflog可以查看所有分支的所有操作记录
(包括已被删除的 commit 记录和 reset 的操作,git log 所不能)

2. 官网介绍

Git 官网

Git 官方文档

Git 官方书

Git 下载页面

Github Git Cheat Sheets - 中文版

Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。

Git 易于学习,占地面积小,性能极快。 它具有廉价的本地库,方便的暂存区域和多个工作流分支等特性。 其性能优于 Subversion、 CVS、 Perforce 和 ClearCase 等版本控制工具。

3. 版本控制介绍

版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。

版本控制其实最重要的是可以记录文件修改历史记录,从而让用户能够查看历史版本,方便版本切换。

为什么需要版本控制?因为要从个人开发过渡到团队协作。

4. 分布式版本控制 VS 集中式版本控制

4.1 集中式版本控制工具

集中化的版本控制系统诸如 CVS、 SVN 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。

这种做法带来了许多好处,每个人都可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个集中化的版本控制系统, 要远比在各个客户端上维护本地数据库来得轻松容易。

事分两面,有好有坏。这么做显而易见的缺点是中央服务器的单点故障。如果服务器宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。

4.2 分布式版本控制工具

Git、 Mercurial、 Bazaar、 Darcs……

像 Git 这种分布式版本控制工具,客户端提取的不是最新版本的文件快照,而是把代码仓库完整地镜像下来(本地库)。这样任何一处协同工作用的文件发生故障,事后都可以用其他客户端的本地仓库进行恢复。因为每个客户端的每一次文件提取操作,实际上都是一次对整个文件仓库的完整备份。

分布式的版本控制系统出现之后, 解决了集中式版本控制系统的缺陷:

  1. 服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)
  2. 每个客户端保存的也都是整个完整的项目(包含历史记录, 更加安全)

5. Git发展历史

6. 工作机制和代码托管中心

6.1 Git 工作机制

6.2 Git 代码托管中心

代码托管中心是基于网络服务器的远程代码仓库,一般我们简单称为远程库

  • 局域网
    • GitLab
  • 互联网
    • GitHub(外网)
    • Gitee 码云(国内网站)

7. Git安装和客户端的使用

Git 下载页面,选择下载 Windows 64 位版的 Git 安装软件。

安装步骤按照安装软件的安装向导安装即可,无需过多配置。

安装成功后,通常在文件浏览器空白处单击击鼠标右键,弹出菜单栏有 Git 的选项。

二、Git 基本使用

命令名称作用
git config --global user.name 用户名设置用户签名
git config --global user.email 邮箱设置用户 email 地址
git init初始化本地库
git status查看本地库状态
git add 文件名添加到暂存区
git commit -m “日志信息” 文件名提交到本地库
git reflog查看历史记录
git reset --hard 版本号版本穿梭

我们先来理解下 Git 工作区、暂存区和版本库概念:

  • 工作区:就是你在电脑里能看到的目录。
  • 暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  • 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
  • 图中左侧为工作区,右侧为版本库。在版本库中标记为 “index” 的区域是暂存区(stage/index),标记为 “master” 的是 master 分支所代表的目录树。
  • 图中我们可以看出此时 “HEAD” 实际是指向 master 分支的一个”游标”。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
  • 图中的 objects 标识的区域为 Git 的对象库,实际位于 “.git/objects” 目录下,里面包含了创建的各种对象及内容。
  • 当执行 git rm –cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。
  • 当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
  • 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
  • 当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。版本库 -> 暂存区
  • 当执行git reset HEAD –hard,暂存区和工作区都会被版本库重写,相当于HEAD指针移动。版本库 -> 暂存区 & 工作区
  • 当执行 git checkout . 或者 git checkout – <file> 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。暂存区 -> 工作区
  • 当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。版本库 -> 暂存区 & 工作区

1. 设置用户签名

1.1 设置系统级用户签名

1
2
git config --global user.name abc #用户名
git config --global user.email abc@123.com

说明:签名的作用是区分不同操作者身,签名邮箱可以是不存在的,Git也不会去验证邮箱是否真实存在。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。 Git 首次安装必须设置一下用户签名,否则无法提交代码

注意这里设置用户签名和将来登录 GitHub(或其他代码托管中心)的账号没有任何关系。

在用户目录下的./gitconfig中查看设置过用户签名

1
2
3
4
5
6
7
8
abc@DESKTOP-R85C9HV MINGW64 ~/Desktop
$ cat ~/.gitconfig
[user]
name = abc
email = abc@123.com
[core]
quotepath = false

1.2 设置仓库级用户签名

1
2
$ git config user.name abc
$ git config user.email abc@163.com

说明:签名的作用是区分不同操作者身份,签名邮箱可以是不存在的,Git也不会去验证邮箱是否真实存在。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。 Git 首次安装必须设置一下用户签名,否则无法提交代码

注意这里设置用户签名和将来登录 GitHub(或其他代码托管中心)的账号没有任何关系。

创建成功,用户签名信息会保存在本地工作区 ./.git/config 文件中,你可以使用 cat 命令查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Administrator@DESKTOP-4054V76 MINGW32 /e/笔记 (master)
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = git@github.com:JYGQAQ/Notebook.git
fetch = +refs/heads/*:refs/remotes/origin/*
[user]
name = JYGQAQ
email = 604713431@qq.com

需要注意的是,签名的作用是区分不同的不同的操作者身份,所以一般只用设置系统级的用户签名。如果两个级别同时存在,那么依照就近原则,仓库级别要大于系统级别。如果两个级别都不存在,则无法完成 Git 一些命令,会提示验证身份。

2. 初始化本地库

基本语法:git init

案例实操:

  • 创建项目目录
1
mkdir gitLearn
  • 进入项目目录
1
cd gitLearn/
  • 初始化本地库
1
2
$ git init
Initialized empty Git repository in E:/gitLearn/.git/

Git自动创建了一个名为. git 非空隐藏文件夹。

3. 查看本地库状态

基本语法:git status

案例实操:

1
2
3
4
5
6
7
Administrator@DESKTOP-4054V76 MINGW32 /e/gitLearn (master)
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

第一行:目前处于哪个本地分支

第二行:从来没有commit过,本地库没有版本信息。

第三行:没有更改需要commit

  • 新建文件后,查看本地库状态
1
2
3
4
5
6
7
8
9
10
11
12
Administrator@DESKTOP-4054V76 MINGW32 /e/gitLearn (master)
$ git status
On branch master

No commits yet

Untracked files:
(use "git add <file>..." to include in what will be committed)

newfile.txt

nothing added to commit but untracked files present (use "git add" to track)

此处,有一个未被追踪的文件newfile.txt被标红),意思是需要git add来提交到暂存区追踪。

有被标红的文件,说明该文件新创建或者和相对于暂存区有更改需要被git add提交到暂存区追踪。

4.添加到暂存区

基本语法:git add 文件名 或者 git add .代表添加所有有更改的文件到暂存区

案例实操:

1
2
3
git add newfile.txt
或者
git add .

接下来使用git status查看本地库状态

注意上面的提示:

可以使用git rm --cached newfile.txt来从索引中删除文件。但是本地文件还存在, 只是不希望这个文件被版本控制,意思是从暂存区中删除newfile.txt

若使用git rm newfile.txt同时从工作区和索引中删除文件。即本地的文件也被删除了。

此处,有一个未被追踪的文件newfile.txt被标绿),意思是需要git commit来提交到本地库,来进行版本控制。

有被标绿的文件,说明该文件未被提交到本地库或者本文件相对于本地库有更改需要被git commit来提交到本地库,来进行版本控制。

git commit -a -m “massage“

​ 其他功能如-m参数,加的-a参数可以将所有已跟踪文件中的执行修改或删除操作的文件都提交到本地仓库,即使它们没有经过git add添加到暂存区,注意,新加的文件(即没有被git系统管理的文件)是不能被提交到本地仓库的。建议一般不要使用-a参数,正常的提交还是使用git add先将要改动的文件添加到暂存区,再用git commit 提交到本地版本库。

git commit --amend

​ 如果我们不小心提交了一版我们不满意的代码,并且给它推送到服务器了,在代码没被merge之前我们希望再修改一版满意的,而如果我们不想在服务器上abondon,那么我们怎么做呢?git commit –amend //也叫追加提交,它可以在不增加一个新的commit-id的情况下将新修改的代码追加到前一次的commit-id中,使得版本库更加清爽。

5. 提交本地库

基本语法:git commit -m "日志信息" 文件名 或者 git commit -m "message"提交所有暂存区内容到本地库。

git commit 主要是将暂存区里的改动给提交到本地的版本库。每次使用git commit 命令我们都会在本地版本库生成一个40位的哈希值,这个哈希值也叫commit-id,commit-id在版本回退的时候是非常有用的,它相当于一个快照,可以在未来的任何时候通过与git reset的组合命令回到这里。

案例实操:

查看本地库状态:

发现没有绿名红名文件被标注,说明没有文件需要被commitadd

5.1 查看本地库版本信息

查看本地库版本信息,使用git reflog查看引用日志信息。

说明:开头是的哈希值是commit-id,最后是commit的message信息。HEAD是指针,指向了master分支。

查看本地库版本的详细信息,使用git log

说明:第一行是commit-id的准确值,第二行是提交者的用户签名,第三行是提交时间,第四行是commitmessage

5.2 Commit Message 规范

git commit命令要求编写commit message,不然无法提交,关于commit message的编写,我们往往容易忽略规范,整体来讲,commit message应该清晰简洁,能够提现本次提交目的。

关于commit message的编写规范,社区有很多种,Angular规范是目前使用最广的写法,本文就简单介绍一下。

commit message的构成包括三部分: Header, Body 和 Footer

1
2
3
4
5
6
7
<type> (<scope>): <subject>
// 空行
<body>
// 空行
<footer>
复制代码

其中,Header是必需的,BodyFooter可以省略。

1
2
3
注意:任何一布行都不得超过 72(或100) 个字符,避免自动换行影响美观
复制代码

5.2.1Header

Header占一行,包括三个字段:type, scope, subject

(1) type

type 用于说明 commit类别,只允许以下 7 个标识:

  • feat: 新功能 (feature)
  • fix: 修补 bug
  • docs: 文档 (documentation)
  • style: 格式 (比如去除空行)
  • refactor: 重构 (不是新增功能,也不是修补 bug)
  • test: 增加测试
  • chore: 构建过程或辅助工具的变动

(2) scope

scope 用于说明 commit 影响的范围,比如数据层、控制层、视图层等等 (很少用到)

(3) subject

描述本次提交的目的,不超过 50 个字符

  • 以动词开头,使用第一人称现在时,比如 change,而不是 changed 或 changes
  • 第一个字母小写
  • 结尾不加句号
5.2.2 Body

Body部分是对本次 commit 的详细描述,可以分为多行描述,要求使用第一人称现在时,说明代码变动原因以及前后行为对比。

Footer 只适用于两种情况:

  • (1) 不兼容变动

当前代码与上一个版本不兼容,则 Footer 部分以 BREAKING CHANGE 开头,后面是对变动的描述、变动理由和迁移方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BREAKING CHANGE: isolate scope bindings definition has changed.

To migrate the code follow the example below:

Before:

scope: {
myAttr: 'attribute',
}

After:

scope: {
myAttr: '@',
}

The removed `inject` wasn't generaly useful for directives so there should be no code using it.
  • (2) 关闭 Issue

如果当前 commit 针对某个 issue,那么可以在 Footer 部分关闭这个 issue

1
Closes #123, #234, #345

6. 修改文件

修改 newfile.txt 内容,git status会提示该文件修改过(会被标红,跟暂存区相比有更改),如下:

git checkout -- file是指根据暂存区的file文件来覆盖工作区的file文件,也就是放弃更改。

需要注意的是,Git是以来管理文件的,最小单位是行。

7. 查看版本之间的不同

7.1 比较工作区与暂存区

1
git diff

git diff 不加参数即默认比较工作区与暂存区

7.2 比较暂存区与最新本地版本库(本地库中最近一次commit的内容)

1
git diff --cached [<path>...] 

git diff 不加参数即默认比较工作区与暂存区2.7.1比较工作区与暂存区

7.3 比较工作区与最新本地版本库

1
git diff HEAD [<path>...] #如果HEAD指向的是master分支,那么HEAD还可以换成master

7.4 比较工作区域指定commit-id的差异

1
git diff commit-id [<path> ...]

7.5 比较暂存区与指定commit-id的差异

1
git diff --cached [<commit-id>][<path>...]

7.6 比较两个commit-id之间的差异

1
git diff [<commit-id>] [<commit-id>]

8. 版本穿梭

8.1 查看历史版本

基本语法:

  • git reflog 查看版本信息
  • git log 查看版本详细信息 加上--graph有图形表示。

git log 与 git reflog 区别

git log 命令可以显示所有提交过的版本信息,如果感觉太繁琐,可以加上参数 --pretty=oneline,只会显示版本号和提交时的备注信息。

git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)。例如,执行 git reset --hard HEAD~1,退回到上一个版本,用git log则是看不出来被删除的 commitid,用git reflog则可以看到被删除的 commitid,我们就可以买后悔药,恢复到被删除的那个版本。link

8.2 版本穿梭

基本语法:

git reset --hard 版本号,**–hard** 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交。

git reset HEADgit resetgit reset --soft HEAD或者git reset --mixed–mixed 为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变。

需要注意的是,上面两种用法,都可以填版本号HEAD ... HEAD^^,唯一不同的是,–hard重写工作区和暂存区,其他只重写暂存区。

Git 切换版本, 底层其实是移动的 HEAD 指针,不会产生新的版本。

三、Git分支用法

1. 分支概述和优点

1.1 什么是分支

在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来, 开发自己分支的时候,不会影响主线分支的运行。对于初学者而言,分支可以简单理解为副本,一个分支就是一个单独的副本。(分支底层其实也是指针的引用)

1.2分支的好处

同时并行推进多个功能开发,提高开发效率。

各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可。

2. 分支基本操作

命令名称作用
git branch 分支名创建分支
git branch -v查看分支
git checkout 分支名切换分支
git merge 分支名把指定的分支合并到当前分支上

2.1 查看分支

基本语法:git branch -v

*代表当前所在的分支

2.2 创建分支

基本语法:git branch 分支名

刚创建的新的分支,并将主分支 master 的内容复制了一份

2.3 切换分支

基本语法:git checkout 分支名

3. 合并分支 (正常合并)

基本语法:git merge 分支名

分支名合并到当前分支。

在 master 分支上合并 hot-fix 分支(将 hot-fix 的合并到 master)。

4. 合并分支 (冲突合并)

4.1 冲突产生的原因

并分支时,多个分支修改了同一个文件(任何地方)或者多个分支修改了同一个文件的名称(从该文件第一行开始,最先开始不同的行到最后不同的行会括起来)。 Git 无法替我们决定使用哪一个,因此,必须人为决定新代码内容。

如果两个分支中分别修改了不同文件中的部分,是不会产生冲突,直接合并即可。

4.2 产生冲突

修改两个分支,中同一文件同一行,合并两个分支:

4.3 解决冲突

编辑有冲突的文件,删除特殊符号,决定要使用的内容。随后git add . & git commit -m "message"正式合并分支。

4.4 创建分支和切换分支

master、 hot-fix 其实都是指向具体版本记录的指针。当前所在的分支,其实是由 HEAD 决定的。所以创建分支的本质就是多创建一个指针。

  • HEAD 如果指向 master,那么我们现在就在 master 分支上。
  • HEAD 如果执行 hot-fix,那么我们现在就在 hot-fix 分支上。

所以切换分支的本质就是移动 HEAD 指针。

5. 远程分支

5.1 创建远程分支

1
2
3
4
git checkout -b my-test  //在当前分支下创建my-test的本地分支分支
git push origin my-test:my-test //将my-test分支推送到远程

git push origin my-test //本地分支和远程分支重名

git push origin my-test:my-test其中第一个my-test是本地分支名,第二个my-test是远程分支名

5.2 建立本地分支与远程分支的联系

1
git branch --set-upstream-to=origin/develop develop

其中,origin是远程仓库的别名,第一个develop是远程分支名,第二个是debelop本地分支名

5.3 查看所有分支

1
git branch -vv

黄色框是本地分支名,绿色框是远程分支名。需要注意的是有些本地分支没有关联远程分支。

四、使用Github

团队内协作

跨团队协作

GitHub 网址

1. 创建远程库

登陆后,点击在网页右上角的 “+” –> “New repository”,创建远程库。

1.1 远程仓库操作

命令名称作用
git remote -v查看当前所有远程地址别名
git remote add 别名 远程地址起别名
git push 别名 分支推送本地分支上的内容到远程仓库
git clone 远程地址将远程仓库的内容克隆到本地
git pull 远程库地址别名 远程分支名将远程仓库对于分支最新内容拉下来后与 当前本地分支直接合并

2. 关联远程库

基本语法

  • git remote -v 查看当前所有远程地址别名
  • git remote add 别名 远程地址

这个地址在创建完远程仓库后生成的连接 ,如图所示

3. 推送本地库到远程库

基本语法:git push 别名 分支 将该分支推送上去

3.1 git push详解

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

如果本地分支名与远程分支名相同,则可以省略冒号:

1
git push <远程主机名> <本地分支名>

如果当前本地分支关联过远程分支:

1
git push

4. 拉取远程库到本地库

需要注意的是,当远程库与本地库不相同时,需要先拉取远程库(如果直接push,会出错)

4.1 git pull详解

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

主要注意的是,git pull之后查看本地库状态,发现本地库是干净的,说明git pull会自动git add .git commit

4.2 日常提交代码到远程库的流程

日常提交代码到远程库的流程如下:

1
2
3
4
git add -A           #需要添加到版本库中的文件 -A 就代表着所有文件(除开了 .gitignore忽略掉的文件)
git commit -m '本次提交的备注'
git pull #将远程的库和本地的库版本同步一下,因为远程库可能发生了修改(多人合作开发时)
git push

这样操作的前提是本地远程都是同一个分支上

4.3 为什么在git push前需要先git pull呢?

  1. 本地和远程的关系相当于两个分支,你感觉一样是因为你git pull 的时候已经自动给绑定好对应关系了, set-upstream..balbala
  2. 你远程新建了一个分支拉到本地的道理是一样的,属于复制了一份,但是本地分支和远程分支已经是两个东西了
  3. 本地分支属于本地仓库里,是包含关系,一个仓库里可以有很多分支, 如果是 tag 的话可以分离出独立的仓库
  4. 肯定不会全量推送到远程的,是通过对比 commit 的记录,如果本地高于远程就直接把多出来的commit 给怼上去,如果本地的这几个 commit 和远程的 commit 有冲突的部分就merge,然后根据提交时间排序再新建一个merge 的 commit 记录再怼上去
  5. 这个先 commit 再 pull 再 push 的情况就是为了应对多人合并开发的情况,
    1. commit 是为了告诉 git 我这次提交改了哪些东西,不然你只是改了但是 git 不知道你改了,也就无从判断比较;
    2. pull是为了本地 commit 和远程commit 的对比记录,git 是按照文件的行数操作进行对比的,如果同时操作了某文件的同一行那么就会产生冲突,git 也会把这个冲突给标记出来,这个时候就需要先把和你冲突的那个人拉过来问问保留谁的代码,然后在 git add && git commit && git pull 这三连,再次 pull 一次是为了防止再你们协商的时候另一个人给又提交了一版东西,如果真发生了那流程重复一遍,通常没有冲突的时候就直接给你合并了,不会把你的代码给覆盖掉
    3. 出现代码覆盖或者丢失的情况:比如A B两人的代码pull 时候的版本都是1,A在本地提交了2,3并且推送到远程了,B 进行修改的时候没有commit 操作,他先自己写了东西,然后 git pull 这个时候 B 本地版本已经到3了,B 在本地版本3的时候改了 A 写过的代码,再进行了git commit && git push 那么在远程版本中就是4,而且 A 的代码被覆盖了,所以说所有人都要先 commit 再 pull,不然真的会覆盖代码的经过本人亲自实验,这种情况不会发生代码覆盖问题
  6. 两个互相合并的唯一区别就是 A->B 的时候 B 分支上会产生一个 merge_commit 的信息,这个时候 B 是合并状态而 A 未合并状态,如果现在没有发生任何改动执行 B->A 就直接切换过去了,连 merge_commit 都不会生成了

这合并的时候发生了什么?

比如你从一个git log为1,2,3,4,5,6的远程库拉取到了本地, 另一个同事也拉取了同样的代码,而且你的同事先于你提交到远程了, 此时远程的版本是1,2,3,4,5,6,7_new,8_new, 而你当前只是本地的版本1,2,3,4,5,6,7_local,8_local,9_local 从这里你就能看出你前一部分和远程的一样,后一部分和远程的不一样, 这个时候你不能正常推送上去的,如果你采取git push origin master --force 那么远程的版本就变成了1,2,3,4,5,6,7_local,8_local,9_local 之前你同事推送的7_new,8_new这两次推送被覆盖了,这不是大家想要的情况 因此需要git pull来将本地的版本合并成样 1,2,3,4,5,6,7_new,7_local,8_local,8_new,9_local,10_commit_merge 远程和本地的排序是按当时 commit 的时间来排的,最后一个10_commit_merge就是你本地远程合并的标志,最后你推送到远程仓库的应该也是这个, 因为你们操作的是同一个库始终要保持代码的同步,所以一旦版本库发生改动同一分支下的所有人都要跟着去同步他,因为各开发各的直接往上推 git 还没智能到帮你处理冲突的地步

5. 克隆远程库到本地

基本语法:git clone 远程地址在远程库获取地址 URL

需要注意的是:远程地址如果是https格式的,任何人都可以克隆。远程地址如果是ssh形式的,只有项目的参与者才可以克隆。在git中clone项目有两种方式:HTTPS和SSH,它们的区别如下: HTTPS:不管是谁,拿到url随便clone,但是在push的时候需要验证用户名和密码; SSH:clone的项目你必须是拥有者或者管理员,而且需要在clone前添加SSH Key。

克隆完成后,查看远程仓库别名,和分支对应情况:

clone 会做如下操作:

  1. 拉取代码。
  2. 初始化本地仓库。
  3. 创建别名。
  4. 创建对应分支

6. 团队内协作

一、选择邀请合作者。(在仓库设置里操作)

二、填入目标合作者。

三、复制网址发送给你目标合作者 , 复制内容如下:https://github.com/atguiguyueyue/git-shTest/invitations。

四、目标合作者接收到网址,用浏览器打开它,点击接受邀请。

五、接受邀请成功之后,可以在目标合作者 Github 账号上看到将来共同开发远程仓库。

六、目标合作者可以修改内容并 push 到远程仓库。

七、回到发送合作邀请者的 GitHub 远程仓库中可以看到,最后一次是目标合作者提交的。

7. 跨团队协作

一、将远程仓库的地址复制发给邀请跨团队协作的人,比如东方不败。

二、在东方不败的 GitHub 账号里的地址栏复制收到的链接,然后点击 网页右上方的 Fork 按钮,将项目叉到自己的本地仓库。

fork成功后可以看到当前仓库信息。

三、东方不败就可以在线编辑fork过来的文件。

四、编辑完毕后,填写描述信息并点击左下角绿色按钮提交。

五、接下来点击上方的 Pull 请求,并创建一个新的请求。

六、回到岳岳 GitHub 账号可以看到有一个 Pull request 请求。

进入到聊天室,可以讨论代码相关内容。

七、如果代码没有问题,可以点击 Merge pull reque 合并代码。

8. SSH 免密登录

ssh配置只是省去了输入github账号密码的这一步操作,所以跟github仓库关系不大,跟github账号关系大

我们可以看到远程仓库中还有一个 SSH 的地址,因此我们也可以使用 SSH 进行访问。

先到用户的主页目录,运行命令 ssh-keygen 生成. ssh 目录:

1
ssh-keygen -t rsa -C "604713431@qq.com"

-t rsa是使用非对称加密协议rsa-C "****"是注释。

在家目录下生成了id_rsa是私钥,放在本地;id_rsa.pub是公钥,放在服务器。

然后,将生成的公钥添加至 Github 账号 SSH 设置

添加公钥后,使用ssh方法可不用输入 Github 账号密码便可push或者pull

五、IDEA集成Git

在IDEA中,红色表示文件新创建并未被add提交到暂存区,绿色代表文件未被commit提交到本地版本库,蓝色代表文件被修改了,需要重新add & commit(此处也可以直接commit)(但是之前被add & commit过)。

git log中绿色标签代表分支,黄色标签代表HEAD头指针。

1. 配置 Git 忽略文件

与项目的实际功能无关,不参与服务器上部署运行。把它们忽略掉能够屏蔽 IDE 工具之间的差异。例如,Maven 工程根据 src 生成的 target。

创建忽略规则文件 xxxx.ignore(前缀名随便起,建议是 git.ignore),这个文件的存放位置原则上在哪里都可以,为了便于让~/.gitconfig 文件引用,建议也放在用户家目录下。

git.ignore 文件模版内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.classpath
.project
.settings
target
.idea
*.iml

在. gitconfig 文件中引用忽略配置文件(此文件在 Windows 的家目录中)

1
2
3
4
5
6
[user]
name = Layne
email = Layne@atguigu.com
[core]
excludesfile = C:/Users/asus/git.ignore

注意:这里要使用 “正斜线(/)”,不要使用 “反斜线(\)”

2. 在 IDEA 配置 Git 程序

在菜单栏 File->Setting-> 搜索栏搜 Git,配置 Git 的安装路径。

3. IDEA初始化 Git

先创建一个名叫 HelloGit 的 Maven 工程。

在菜单栏 VCS -> Import into Version Control -> Create Git Repository

选择要创建 Git 本地仓库的工程,也就是 HelloGit 工程,然后添加 OK。

4. 添加到暂存区

创建一个 HelloGit 类,将其添加 Git 暂存区。

右键点击 HelloGit 类,选择 Git->Add。可以右键点击 HelloGit项目根目录,更大范围地添加文件到暂存区。

添加成功后,文件名会从红色变成绿色。

5. 提交至本地库

右键点击 HelloGit,选择 Git->Commit Directory。

添加注释后提交:

添加成功后,后台打印相关信息。

6. 切换版本

在 IDEA 的左下角,点击 Git,然后点击 Log 查看版本

右键选择要切换的版本,然后在菜单里点击 Checkout Revision。

7. 创建分支

右键点击 HelloGit,Git -> Repository -> Branches,或者点击 IDEA 的右下角,如图红圈所示部位:

选择点击 New Branch:

创建新分支:

8. 切换分支

创建分支步骤相似,如点击 IDEA 的右下角(它显示项目正处在那条分支),如图红圈所示部位,选择你想要切换的分支,然后 checkout:

或者在 log 窗口,右键点击分支,选择 checkout:

9. 合并分支 (正常合并)

先在 hot-fix 分支修改 HelloGit 类,并将其提交:

然后切换到 master 分支,右下角的 hot-fix 会变为 master:

然后,点击 IDEA 窗口的右下角的 master,将 hot-fix 分支合并到当前 master 分支。选择 hot-fix->Merge into Current

如果代码没有冲突, 分支直接合并成功,分支合并成功以后,代码自动提交,无需手动提交本地库。

10. 合并分支 (冲突合并)

分别在 master,hot-fix 分支修改 HelloGit 类同一行,并提交,故意制作冲突:

切换到 master 分支,将 hot-fix 的合并到 master 分支:

冲突产生,需要人工解决:

代码冲突解决,将代码提交本地库后,如图所示:

六、IDEA集成GitHub

1. 设置 GitHub 账号

在菜单栏 File->Setting-> 搜索栏搜 GitHub,添加 GitHub 账号:

由于网络问题,会时常登陆不了:

解决方法:可通过 Token 登陆。

登陆 Github 网站,获取 Token,操作步骤看下图:

将生成的 token 用来 IDEA 登录。

2. 分享项目到 GitHub

3. 推送代码到GitHub远程库

注意: push 是将本地库代码推送到远程库,如果本地库代码跟远程库代码版本不一致,push 的操作是会被拒绝的。也就是说, 要想 push 成功,一定要保证本地库的版本要比远程库的版本高! 因此一个成熟的程序员在动手改本地代码之前,一定会先检查下远程库跟本地代码的区别!如果本地的代码版本已经落后,切记要先 pull 拉取一下远程库的代码,将本地代码更新到最新以后,然后再修改,提交,推送!

4. 拉取GitHub远程库代码合并本地库

右键点击项目,可以将远程仓库的内容 pull 到本地仓库。

注意: pull 是拉取远端仓库代码到本地,如果远程库代码和本地库代码不一致,会自动合并,如果自动合并失败,还会涉及到手动解决冲突的问题。

5. 克隆代码到本地

在菜单栏的 File->Close Project->Get from Version Control。

或者在菜单栏 VCS->Get from Version Control。

七、Gitee使用

1. Gitee简介 & 创建远程库

1.1 码云简介

众所周知, GitHub 服务器在国外, 使用 GitHub 作为项目托管网站,如果网速不好的话,严重影响使用体验,甚至会出现登录不上的情况。针对这个情况, 大家也可以使用国内的项目托管网站 - 码云。

码云是开源中国推出的基于 Git 的代码托管服务中心, 网址是 https://gitee.com/ ,使用方式跟 GitHub 一样,而且它还是一个中文网站,如果你英文不是很好,它是最好的选择。

而且,Gitee的操作和GitHub基本一样。

1.2 创建远程库

跟 Github 的类似。

另外,可以从 GitHub 与 GitLab 中导入仓库。

点击刷新按钮,从GitHub获取更新

3441eab01ee412c90cb4f2be908833f

2. IDEA 集成 Gitee 码云

首先,要在 IDEA 安装 Gitee 插件。

在菜单栏选 File->Settings->Plugins,搜 Gitee。

安装插件成功后,重启 IDEA。

功能跟在 IDEA 的 Github 插件,功能类似,如添加 Gitee 账号等,可参考前文 IDEA 的 Github 插件,触类旁通。

八、GitLab

1. GitLab简介 & 安装环境准备

1.1 GitLab 简介

GitLab 是由 GitLab Inc. 开发,使用 MIT 许可证的基于网络的 Git 仓库管理工具,且具有 wiki 和 issue 跟踪功能。使用 Git 作为代码管理工具,并在此基础上搭建起来的 web 服务。(可搭建局域网 Git 仓库)。

GitLab 由乌克兰程序员 DmitriyZaporozhets 和 ValerySizov 开发,它使用 Ruby 语言写成。后来,一些部分用 Go 语言重写。截止 2018 年 5 月,该公司约有 290 名团队成员,以及 2000 多名开源贡献者。 GitLab 被 IBM, Sony, JülichResearchCenter, NASA, Alibaba,Invincea, O’ReillyMedia, Leibniz-Rechenzentrum(LRZ), CERN, SpaceX 等组织使用。

1.2 GitLab 官网地址

官网地址

安装说明

1.3 GitLab 安装准备

  1. 准备一个系统为 CentOS7 以上版本的服务器, 要求内存 4G,磁盘 50G。
  2. 关闭防火墙, 并且配置好主机名和 IP,保证服务器可以上网。
  3. 此教程使用虚拟机:主机名: gitlab-server 修改/etc/hostname文件为gitlab-serverIP 地址: 192.168.6.200(修改相对应文件)
  4. Yum 在线安装 gitlab- ce 时,需要下载几百 M 的安装文件,非常耗时,所以最好提前把所需 RPM 包下载到本地,然后使用离线 rpm 的方式安装。下载地址。注:资料里提供了此 rpm 包,直接将此包上传到服务器 / opt/module 目录下即可。

2. GitLab 安装 & 初始化服务 & 启动服务

2.1 编写安装脚本

安装 gitlab 步骤比较繁琐,因此我们可以参考官网编写 gitlab 的安装脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@gitlab-server module]# vim gitlab-install.sh
sudo rpm -ivh /opt/module/gitlab-ce-13.10.2-ce.0.el7.x86_64.rpm

sudo yum install -y curl policycoreutils-python openssh-server cronie

sudo lokkit -s http -s ssh

sudo yum install -y postfix

sudo service postfix start

sudo chkconfig postfix on

curl https://packages.gitlab.com/install/repositories/gitlab/gitlabce/script.rpm.sh | sudo bash

sudo EXTERNAL_URL="http://gitlab.example.com" yum -y install gitlabce

给脚本增加执行权限

1
2
3
4
5
6
7
[root@gitlab-server module]# chmod +x gitlab-install.sh
[root@gitlab-server module]# ll
总用量 403104
-rw-r--r--. 1 root root 412774002 4 月 7 15:47 gitlab-ce-13.10.2-
ce.0.el7.x86_64.rpm
-rwxr-xr-x. 1 root root 416 4 月 7 15:49 gitlab-install.sh

然后执行该脚本,开始安装 gitlab-ce。注意一定要保证服务器可以上网。

1
2
3
4
5
6
7
8
9
10
[root@gitlab-server module]# ./gitlab-install.sh
警告: /opt/module/gitlab-ce-13.10.2-ce.0.el7.x86_64.rpm: 头 V4
RSA/SHA1 Signature, 密钥 ID f27eab47: NOKEY
准备中... #################################
[100%]
正在升级/安装...
1:gitlab-ce-13.10.2-ce.0.el7
################################# [100%]
。 。 。 。 。 。

2.2 初始化 GitLab 服务

执行以下命令初始化 GitLab 服务,过程大概需要几分钟,耐心等待…

1
2
3
4
5
6
7
8
[root@gitlab-server module]# gitlab-ctl reconfigure
。 。 。 。 。 。
Running handlers:
Running handlers complete
Chef Client finished, 425/608 resources updated in 03 minutes 08
seconds
gitlab Reconfigured!

2.3 启动 GitLab 服务

执行以下命令启动 GitLab 服务,如需停止,执行 gitlab-ctl stop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@gitlab-server module]# gitlab-ctl start
ok: run: alertmanager: (pid 6812) 134s
ok: run: gitaly: (pid 6740) 135s
ok: run: gitlab-monitor: (pid 6765) 135s
ok: run: gitlab-workhorse: (pid 6722) 136s
ok: run: logrotate: (pid 5994) 197s
ok: run: nginx: (pid 5930) 203s
ok: run: node-exporter: (pid 6234) 185s
ok: run: postgres-exporter: (pid 6834) 133s
ok: run: postgresql: (pid 5456) 257s
ok: run: prometheus: (pid 6777) 134s
ok: run: redis: (pid 5327) 263s
ok: run: redis-exporter: (pid 6391) 173s
ok: run: sidekiq: (pid 5797) 215s
ok: run: unicorn: (pid 5728) 221s

3. GitLab 登录 & 创建远程库

3.1 登录 GitLab

使用主机名或者 IP 地址即可访问 GitLab 服务。可配一下 windows 的 hosts 文件(C:\Windows\System32\drivers\etc)。

首次登陆之前,需要修改下 GitLab 提供的 root 账户的密码,要求 8 位以上,包含大小写子母和特殊符号。

然后使用修改后的密码登录 GitLab。

GitLab 登录成功。

3.2 创建远程库

4. IDEA 集成 GitLab

接下来插件配置,Git 操作等与 Github、Gitee 的 IDEA 插件大同小异,不再赘述,自己触类旁通吧!

九、Git报错处理

1.SSL报错

1
fatal: unable to access 'https://github.com/.......': OpenSSL SSL_read: Connection was reset, errno 10054

产生原因:一般是这是因为服务器的SSL证书没有经过第三方机构的签署,所以才报错。参考网上解决办法:解除ssl验证后,再次git即可。

1
git config --global http.sslVerify "false"

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!