前言

Git官网
图片

Git工作机制

图片

Git工作仓库

局域网 互联网
GitLab Github
Gitee

Git常用命令

命令 说明
git config –global user.name 用户名 设置用户签名(用户名)
git config –global user.email 邮箱 设置用户签名(邮箱)
git init 初始化本地库
git status 查看本地库状态
git diff 显示工作目录与暂存区之间的文件变更
git add 文件名 添加到暂存区(索引区)
git commit -m “日志信息” 文件名 提交到本地库
git reflog 查看提交的历史记录(及版本号)
git reset –hard 版本号 版本切换(可实现撤销commit提交)
git checkout – 文件名 丢弃工作区的修改
git checkout . 丢弃工作区所有文件的修改
git reset HEAD 把暂存区的修改撤销掉,重新放回工作区

图片

工作区(workspace)、暂存区/索引区(index)、本地版本库(repository)、远程仓库(remote)

实例操作

全局范围的签名设置

1
2
3
$ git config --global user.name ooahz

$ git config --global user.email xxxx@ahzoo.cn

查看配置信息

1
$ cat ~/.gitconfig

**Git 首次安装必须设置一下用户签名,否则无法提交代码。 **
这里设置用户签名和登录 GitHub(或其他代码托管中心)的账号没有任何关系。
签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁进行的

当前仓库范围的签名设置

1
2
3
$ git config user.name ooahz

$ git config user.email xxxx@ahzoo.cn

初始化本地仓库

1
$ git init

操作完成后,可以在本地看到生成的一个**.git**隐藏文件夹
图片

查看本地库状态

1
2
3
4
5
6
$ git status
On branch master

No commits yet

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

新增文件

创建文件

1
$ vim hello.txt

然后使用vim命令,编写文件,随便写点文字用于测试

1
2
$ cat hello.txt
hello world

Vim编辑器常用快捷键

再次查看状态

1
2
3
4
5
6
7
8
9
10
$ git status
On branch master

No commits yet

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

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

添加暂存区

1
$ git add hello.txt

如果要添加路径下所有文件可以直接使用git add .命令

查看状态:

1
2
3
4
5
6
7
8
$ git status
On branch master

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.txt

提交本地库

1
2
3
4
5
6
$  git commit -m "提交测试" hello.txt
warning: LF will be replaced by CRLF in hello.txt.
The file will have its original line endings in your working directory
[master (root-commit) 9bdf471] 提交测试
1 file changed, 1 insertion(+)
create mode 100644 hello.txt

“日志信息”后面的文件名可省略,省略后表示对此次提交的所有文件添加此日志信息

查看状态:

1
2
3
$ git status
On branch master
nothing to commit, working tree clean

修改文件

1
vim hello.txt

随便修改几个字符用于测试:

1
2
$ cat hello.txt
hello word 001

对比文件

1
2
3
4
5
6
7
8
$ git diff
diff --git a/hello.txt b/hello.txt
index 3f5f37d..d0a500f 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-hello world
+hello world 001

git diff –cached 或 git diff –staged:显示索引区(暂存区)和最后一次commit(HEAD)之间的文件更改
git diff HEAD:显示工作目录与最后一次commit之间的文件变更
git diff <分支名1> <分支名2> :比较两个分支上最后 commit 的内容的差别

同样提交修改后的文件

1
2
3
4
5
$ git add hello.txt

$ git commit -m "修改提交"
[master 67b42c5] 修改提交
1 file changed, 1 insertion(+), 1 deletion(-)

历史版本

1
2
3
$ git reflog
67b42c5 (HEAD -> master) HEAD@{0}: commit: 修改提交
9bdf471 HEAD@{1}: commit (initial): 提交测试

git reflog 查看版本信息
git log 查看版本详细信息
此处的 67b42c5 和 9bdf471 即为版本号

版本切换

将版本切换到初次提交时的版本

1
2
$ git reset --hard 9bdf471
HEAD is now at 9bdf471 提交测试

查看文件:

1
2
$ cat hello.txt
hello world

Git切换版本,底层其实是移动的HEAD指针

图片

分支操作

在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独
分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时
候,不会影响主线分支的运行。

图解分支的创建与切换:
图片
图片

操作命令

命令 说明
git branch 分支名 创建分支
git branch -v 查看分支
git checkout 分支名 切换分支
git merge 分支名 把指定的分支合并到当前分支上
git branch -D 分支名 删除分支

实例操作

创建分支

创建名为hot-fix的分支

1
$ git branch hot-fix

查看分支信息

1
2
3
$ git branch -v
hot-fix 9bdf471 提交测试
* master 9bdf471 提交测试

可以看到创建分支时会将主分支master的内容复制一份

切换分支

切换到hot-fix分支

1
$ git checkout hot-fix

可以看到右侧的master变成了hot-fix(可见下图)

合并分支

冲突的产生

修改hot-fix分支的文件,与master分支上文件修改的位置保持一致(这样就会产生冲突)

1
$ vim hello.txt

查看修改

1
2
$ cat hello.txt
hello world 002

提交修改

1
2
3
$ git commit -m "分支修改"
[hot-fix acb64ed] 分支修改
1 file changed, 1 insertion(+), 1 deletion(-)

切换回master分支

1
2
3
$ git checkout master
Switched to branch 'master'
M hello.txt

因为之前将master分支的版本切回了未修改时的,所以需要切换回修改后的版本,或者直接重新修改提交亦可;

1
2
$ git reset --hard 67b42c5
HEAD is now at 67b42c5 修改提交

查看文件:

1
2
$ cat hello.txt
hello world 001
合并分支

由于此时在master,所以需要合并的分支就是hot-fix

1
git merge hot-fix 

冲突报错:

1
2
3
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.

图片

解决冲突

冲突产生的原因:
合并分支时,两个分支在同一个文件的同一个位置有两套完全不同的修改。Git 无法替我们决定使用哪一个。必须人为决定新代码内容。

查看状态:

1
2
3
4
5
6
7
8
9
10
11
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hello.txt

no changes added to commit (use "git add" and/or "git commit -a")

根据返回结果可以看到文件有两个参数,这就造成了冲突

进入文件,手动修改

1
$ vim hello.txt
1
2
3
4
5
<<<<<<< HEAD
hello world 001
=======
hello world 002
>>>>>>> hot-fix

<<<<<<< HEAD 当前分支的代码 ======= 合并过来的代码 >>>>>>> hot-fix

手动修改文件,修改后:

1
hello world 001

重新提交文件:

1
2
3
4
$ git add hello.txt

$ git commit -m "修改合并文件"
[master cd73e7f] 修改合并文件

查看文件:

1
2
$ cat hello.txt
hello world 002

删除分支

1
2
$ git branch -D hot-fix
Deleted branch hot-fix (was acb64ed).

Git 仓库(Git远程仓库操作)

以Github为例(其他仓库也基本大同小异)

创建仓库

点击头像旁边的加号,选择** New repository**;

图片

直接输入仓库名,勾选创建一个初始的readme文件(非必要),然后点击创建即可
图片

j进入仓库后,点击Code即可看到仓库的远程地址
图片

远程仓库操作

命令 说明
git remote -v 查看当前所有远程地址别名
git remote add 别名 远程地址 为远程地址添加别名
git remote rename 原别名 新别名 为远程地址修改别名
git remote rm 别名 为远程地址删除别名
git push 别名 分支 推送本地分支上的内容到远程仓库
git clone 远程地址 将远程仓库的内容克隆到本地
git pull 远程库地址别名 远程分支名 将远程仓库对于分支最新内容拉下来后与
当前本地分支直接合并

实例操作

克隆远程仓库

1
2
3
4
5
6
$ git clone https://github.com/ooahz/mytest.git
Cloning into 'mytest'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.

图片

克隆指定分支的指定版本

首先克隆指定分支的所有版本(git clone默认克隆所有版本)

1
$ git clone 仓库地址 -b 分支名称

-b--branch的简写

然后切换版本

1
$ git reset --hard 版本号
克隆指定分支部分版本
1
$ git clone --depth=1 仓库地址 --branch 分支名称

--depth=1表示克隆深度为1,即只克隆最近一次的提交版本;同理--depth=9表示克隆最近9次的提交版本

如果不想指定分支就直接把--branch 分支名省略即可

但是,这样克隆会导致无法切换到其他分支,所以需要配合下面命令来切换到其他分支:

添加分支–>获取分支–>切换分支

1
2
3
4
5
$ git remote set-branches --add origin 分支名称

$ git fetch origin 分支名称

$ git checkout 分支名称

添加远程仓库

1
$ git remote add myGitTest https://github.com/ooahz/mytest.git

设置完成后查看别名:

1
2
3
$ git remote -v
myGitTest https://github.com/ooahz/mytest.git (fetch)
myGitTest https://github.com/ooahz/mytest.git (push)

可以看到远程仓库( https://github.com/ooahz/mytest.git)的别名已经被设置成了myGitTest

推送到远程仓库

在本地仓库新建一个文件
添加到本地仓库:

1
2
3
4
5
6
7
$ git add .

$ git commit -m "测试"
[master 2ac4b5d] 测试
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 "\346\226\260\345\273\272\346\226\207\346\234\254\346\226\207\346\241\243.txt"

将本地仓库分支推送到远程仓库

1
2
3
4
5
6
7
8
9
10
$ git push myGitTest master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 286 bytes | 286.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/ooahz/mytest.git
09e2fea..2ac4b5d master -> master

进入github查看:
图片

拉取远程仓库

修改刚刚上传的文件内容(上传时是空文件,上传后添加了一段文字:“ahzoo”

图片
然后新建一个·文件(拉取测试)
图片
开始拉取操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ git pull myGitTest master
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), done.
From https://github.com/ooahz/mytest
* branch master -> FETCH_HEAD
2ac4b5d..d0c748e master -> myGitTest/master
Updating 2ac4b5d..d0c748e
Fast-forward
"\346\213\211\345\217\226\346\265\213\350\257\225" | 1 +
...\260\345\273\272\346\226\207\346\234\254\346\226\207\346\241\243.txt" | 1 +
2 files changed, 2 insertions(+)
create mode 100644 "\346\213\211\345\217\226\346\265\213\350\257\225"

图片

git pull 与 git clone 的区别:
git clone是直接将远程仓库克隆到本地,是一个从无到有的过程
git pull 是拉取远程仓库合并到本地,是一个更新过程

总结

还是结合这张图:

图片

工作区(workspace)、暂存区/索引区(index)、本地版本库(repository)、远程仓库(remote)

  • 前提

可以看到进行git操作之前,必须要先创建工作区。即进行git操作时要先拥有一个git仓库,如果没有则需要使用git init命令初始化git仓库

而进行远程仓库操作时,都是需要远程仓库支持。即进行远程仓库操作时需要关联远程仓库,如果没有则需要使用git remote命令关联远程仓库

示例:

1
2
3
$ git init

$ git remote add origin https://github.com/ooahz/mytest.git
  • 拉取操作

在完成上面两个前提操作后,我们就可以进行拉取操作。结合上面那张图,可以看到拉取操作只需要从远程仓库拉取(pull)即可。

示例:

1
$ git pull origin master
  • 推送操作

在完成上面两个前提操作后,我们就可以进行推送操作。结合上面那张图,可以看到推送操作需要先将本地仓库添加到索引区,然后再提交到本地库,最后才能进行推送操作。

示例:

1
2
3
4
5
$ git add .

$ git commit -m "版本推送说明"

$ git push origin master

团队协作

团队内协作

图片

跨团队协作

图片

fork别的仓库到自己仓库(dev分支)–>在自己仓库修改–>pull推送给原作者(master分支)

IDEA整合Git

配置Git 忽略文件

忽略原则:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

举个例子:
图片
图片

方法一

创建忽略文件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

然后添加忽略文件:
在C盘的用户路径下,找到名为.gitconfig的文件;
打开后可以看到之前配置的全局范围签名信息,在后面添加忽略文件路径即可

1
2
3
4
5
[user] 
name = ooahz
email = xxx@ahzoo.cn
[core]
excludesfile = C:/Users/ahzoo/git.ignore

方法二

打开IDEA:File | Settings | Editor | File Types;
在Ignore files and folders中添加需要忽略的文件或者文件夹
图片

配置Git路径

图片

初始化Git仓库

VCS–>import into Version Control–>Creat Git Repository;
图片

然后选择要创建本地仓库的项目

添加到暂存区

右键项目,Gitt–>Add
图片

提交到本地库

右键项目,Gitt–>Commit Directory
选择要提交的文件,输入提交信息,然后点击commit提交;
图片

切换版本

右下角点击Git,选择Log,右键要切换的版本,选择Checkout Revision
图片

分支操作

项目右键选择Git–>Repository –>Branches (或者直接点击右下角的分支名)
图片

创建分支

在弹出的分支弹窗中,点击new Branch;
图片
输入分支名,创建即可
图片

切换分支

直接在弹出的分支弹窗中选择要切换的分支,然后点击Checkout即可;
图片
切换完成后,在IDEA右下角可以看到当前分支
图片

合并分支

直接在弹出的分支弹窗中选择要切换的分支,然后点击Merge into Current即可;
图片

冲突解决

可参照前面Git中的解决方法

Bug分支

适用场景:线上需要紧急修复bug,而当前dev分支中又有开发到一半的需求,因此此时不能在dev分支上进行修复,就需要创建一个Bug分支,对当前Bug进行修复。
因为要对master分支的bug进行修复,所以,在Idea中打开分支;
在master分支中选择New Branch from Selected
图片
输入分支名
图片
在bug分支修复完bug后,切回master分支

然后选择刚才修复bug的分支,选择Marge into Curent合并到master分支即可

图片
修复完master上的分支后再切回dev分支,将修复bug的分支合并到dev分支
图片
合并完后删除bug分支

IDEA整合GitHub

Gitee同理,只需要在IDEA安装Gitee插件即可;

配置SSH

配置SSH密钥,实现免密登录(首次提交时仍需要验证密码)

1
$ ssh-keygen -t rsa -C "github绑定的邮箱"

连续敲回车确定,然后看到提示秘钥以保存在xxx路径下(如果没有出现提示就多敲几次回车)。
在提示的路径下找到id_rsa文件,复制文件内容。
图片
图片
登陆你的Github帐号,点击头像进入settings,点击SSH and GPG keys–>New SSH key,输入刚才复制的密钥命名保存,完成(提交仓库的链接记得选SSH而不是HTTPS)
图片

创建个人访问令牌(Personal Access Tokens)

点击右侧头像,依次选择Settings→Developer settings→Personal access tokens→Generate new token;
图片
输入note名,勾选需要的功能(不知道就全√),然后选择底部的生成令牌按钮;
图片
复制生成的Token,需要注意的是,此Token只会显示一次,所以需要妥善保管(丢了就按照步骤重新创建一次)
图片

添加账户

依次打开:File | Settings | Version Control | GitHub
图片
输入账号密码,或者左上角选择Use Token(使用个人访问令牌登录)
图片

图片

分享项目到远程仓库

VCS–>Import into Version Control–>Share Project on Github
图片
设置仓库名(Repository name),远程版本库名(Remote),简介(Description),点击Share分享
图片

图片
图片

克隆远程仓库到本地

进入IDEA首页,选择Get from Version Control

图片

输入远程仓库地址:

图片

点击CLONE等待克隆完成

设置本地库

点击顶部菜单栏的VCS–>Create Git Repository,设置Git仓库

图片

图片

设置完Git仓库后,顶部菜单的VCS会变成Git

修改本地库

如果本地库设置错了,可在设置中进行修改:

点击:File | Settings | Version Control | Directory Mappings

可以在这里对本地库进行相应的操作

图片

添加远程仓库

点击顶部菜单栏的Git–>Manage Remotes

图片

点击+号,设置远程仓库地址,并自定义别名

图片

拉取远程项目到本地

修改本地项目:
图片
拉取远程仓库:
选择项目右键,Git–>Repository–>Pull
图片

如之前未设置Git仓库及关联远程仓库,会出现下面的弹窗提示进行相关操作:

设置当前项目路径,远程仓库地址(一般都是默认即可),然后点击Pull,开始拉取远程仓库
图片

推送项目到远程仓库

首先将项目【提交到本地库】(参照上文的IDEA整合Git部分);
然后将本地库上传到远程库;
选择项目右键,Git–>Repository–>Push
图片

后记

报错一:

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

解决方法,使用SSH代替HTTPS(必须要先配置SSH才行)
图片
报错二:
账户密码输入正常,却无法登录

1
Logon failed, use ctrl+c to cancel basic credential prompt.

解决方法:
使用个人令牌登录;
在密码栏输入个人令牌即可

问题三:
git push时提示:

1
Everything up-to-date

原因:修改本地仓库时未进行提交
解决方法:添加本地仓库并提交:

1
2
3
$ git add .

$ git commit -m "推送测试"

问题四:
使用git add命令时提示:

1
2
3
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.

解决方法一:
使用-f强制添加

1
$ git add -f App.class

解决方法二:
检查是否为.gitignore配置的问题:
使用命令git check-ignore -v 文件名

1
2
$ git check-ignore -v App.class
.gitignore:7:*.class App.class

可以看到是.gitignore配置文件的第7行忽略.class文件

问题五:
配置SSH时出现提示:

1
unknow key type ras

解决方法:
使用以下命令替换

1
ssh-keygen -C"邮箱地址"

问题六:
使用IDEA推送(pull)项目时失败,报错:

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

解决方法:
修改远程仓库地址(remote)
选择项目右键,Git–>Repository–>Remotes
图片
新建一个,如果远程版本库名就直接编辑已有的远程仓库地址;
图片
因为使用HTTPS报错了,所以需要使用SSH连接;
填入远程版本库名(默认为origin)和远程仓库的SSH地址,点击OK保存
图片
问题七:
修改/创建remote时报错:

1
2
3
4
The authenticity of host 'github.com (20.205.243.166)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

原因:本地SSH与远程仓库不一致;
解决方法:参照【配置SSH】将SSH设为一致即可