Skip to content

Git基础教程

Git概述

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

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

分布式版本控制工具VS集中式版本控制工具。

版本控制工具

1、集中式版本控制工具

CVS、SVN(Subversion)、VSS……

2、分布式版本控制工具

Git、Mercurial、Bazaar、Darcs……

Git工具机制

工作区(写代码)->git add->暂存区(临时存储)->git commit->本地库(历史版本)->pull->远程库

Git和代码托管中心

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

1、局域网

GitLab

2、互联网

Github(外网)
Gitee码云(国内网站)

Git安装

官网地址

查看GNU协议,可以直接点击下一步。

Git的安装要选择非中文没有空格的目录

git-base-001

git-base-002

git-base-003

git-base-004

这里推荐选择默认的第二个,我初学的时候选择了第一个,看自己情况,我这选择第一个就得打开Git带的Bash才能使用,默认的是可以之间在CMDPowershell中就可以直接使用。下面除了路径其他都推荐默认的就行了。

Git常用命令

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

设置用户签名

签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。
Git首次安装必须设置以下用户签名,否则无法提交代码。

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

这里我在centos7上安装了git来使用。

bash
git --version  
git config --global user.name ggt  
git config --global user.email ggt@pqpq.com

邮箱可以是虚拟邮箱,不会去验证邮箱。

bash
cat ~/.gitconfig
[user]
        name = ggt
        email = ggt@pqpq.com

以上输出内容是验证用户签名成功了。

初始化本地库

在初始化本地库之前,需要先cd到项目目录中。

bash
mkdir git && cd git
bashgit init

git初始化之后会在项目目录中生成 .git 的文件。

查看本地库状态

bash
bashgit status 
On branch master

No commits yet

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

On branch master:当前本地库在master分支。
No commits yet:目前还没有提交过东西。
nothing to commit:没有什么东西需要提交。

bash
bashcat hello.txt 
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!

bashgit 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)

Untracked files:有一些文件在Git仓库还没有被跟踪。

添加暂存区

bash
bashgit add hello.txt

bashgit status 
On branch master

No commits yet

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

Changes to be committed:检测到暂存区有新文件。

此时hello.txt就已经在暂存区了,这时候如果不想要了可以使用以下命令删除暂存区这个hello.txt

bash
bashgit rm --cached hello.txt

提交本地库

git commit -m "日志信息" 文件名

bash
bashgit commit -m "first commit" hello.txt 
[master (root-commit) 2266eb8] first commit
 1 file changed, 16 insertions(+)
 create mode 100644 hello.txt

master:当前所在的分支名称。
root-commit:表示这是一个根提交,即在这个分支上的第一个提交。
2266eb8:是该提交的哈希值。
1 file changed, 16 insertions:1个文件被更改,16行代码被添加。
create mode 100644 hello.txthello.txt文件已经创建并添加到仓库中;create mode表示一个新创建的文件;100644:该文件的权限,即普通文件。

bash
bashgit status 
On branch master
nothing to commit, working tree clean

bashgit reflog 
2266eb8 (HEAD -> master) HEAD@{0}: commit (initial): first commit

bashgit log 
commit 2266eb82d052d710c73ed69338946aa6d5d774ad (HEAD -> master)
Author: ggt <ggt@pqpq.com>
Date:   Tue Apr 25 22:59:36 2023 +0800

    first commit

修改文件

bash
bashcat hello.txt 
hello git! 2222222222
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!

此时查看本地库状态,提示被修改了

bash
bashgit status 
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   hello.txt

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

bashgit add hello.txt

bashgit status 
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   hello.txt

bashgit commit -m "second commit" hello.txt 
[master 6d75c5f] second commit
 1 file changed, 1 insertion(+), 1 deletion(-)

bashgit status 
On branch master
nothing to commit, working tree clean

历史版本

1、查看历史版本

git reflog查看版本信息
git log查看版本详细信息

bash
bashgit reflog 
6d75c5f (HEAD -> master) HEAD@{0}: commit: second commit
2266eb8 HEAD@{1}: commit (initial): first commit

2、版本穿梭

git reset --hard 版本号

我这是要穿梭到 first commit这个版本,这个版本的版本号为2266eb8

bash
bashgit reset --hard 2266eb8
HEAD is now at 2266eb8 first commit

bashgit reflog 
2266eb8 (HEAD -> master) HEAD@{0}: reset: moving to 2266eb8
6d75c5f HEAD@{1}: commit: second commit
2266eb8 (HEAD -> master) HEAD@{2}: commit (initial): first commit

bashgit log
commit 2266eb82d052d710c73ed69338946aa6d5d774ad (HEAD -> master)
Author: ggt <ggt@pqpq.com>
Date:   Tue Apr 25 22:59:36 2023 +0800

此时查看文件,发现文件已经变化,回到了first commint这个版本

bash
bashcat hello.txt 
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!

.git下有一个HEAD文件,这里的指针指向的是master,说明当前是在master这个分支上

bash
bashcat .git/HEAD 
ref: refs/heads/master

如何知道当前在master分支的哪个版本上

bash
bashcat .git/refs/heads/master
2266eb82d052d710c73ed69338946aa6d5d774ad

Git切换版本,底层其实是移动的HEAD指针,具体原理如下所示。

head->master->first

Git分支操作

git-base-005

什么是分支

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

git-base-006

hot-fixmasterfeature-bluefeture-game 就是不同的项目开发,而最终会合并都master分支上。

分支的好处

同时并行推进多个功能开发,提高开发效率。
各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可。

分支的操作

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

1、查看分支

bash
bashgit branch -v
* master 2266eb8 first commit

2、创建分支

创建分支的同时,会将主分支master的内容复制一份

bash
bashgit branch hot-fix

再次查看分支,发现多了hot-fix分支,前面有*的就是当前所在的分支

bash
bashgit branch -v
  hot-fix 2266eb8 first commit
* master  2266eb8 first commit

3、切换分支

bash
bashgit checkout hot-fix 
Switched to branch 'hot-fix'

修改hot-fix分支下的hello.txt,并提交到本地库

bash
bashcat hello.txt 
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

bashgit add hello.txt

bashgit commit -m "hot-fix commit" hello.txt
[hot-fix 1f82e98] hot-fix commit
 1 file changed, 1 insertion(+), 1 deletion(-)

此时master分支下的hello.txt文件内容为

bash
bashcat hello.txt
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!

4、合并分支(正常)

master分支上操作合并

bash
bashgit checkout master 
Switched to branch 'master'

bashgit merge hot-fix 
Updating 2266eb8..1f82e98
Fast-forward
 hello.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

此时master分支下的hello.txt文件内容为

bash
bashcat hello.txt 
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

5、合并分支(产生冲突)

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

修改master分支下的hello.txt,并提交到本地库

bash
bashcat hello.txt 
hello git! master merge
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

bashgit add hello.txt 
bashgit commit -m "master merge" hello.txt 
[master 10ee3b4] master merge
 1 file changed, 1 insertion(+), 1 deletion(-)

修改hot-fix分支下的hello.txt,并提交到本地库

bash
bashcat hello.txt 
hello git!
hello git! hot-fix merge
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

bashgit add hello.txt 
bashgit commit -m "hot-fix merge" hello.txt 
[hot-fix 17e8b4e] hot-fix merge
 1 file changed, 1 insertion(+), 1 deletion(-)

master分支上操作合并

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

Auto-merging hello.txt:在合并过程中Git已经自动尝试合并对该文件的修改。

CONFLICT (content): Merge conflict in hello.txt:这是一个冲突的指示。它告诉你在合并过程中发生了冲突,并且冲突发生在hello.txt文件中。冲突类型是内容冲突,表示两个分支对同一部分代码进行了修改,并且Git无法自动解决冲突。

Automatic merge failed; fix conflicts and then commit the result.:这行消息告诉你自动合并失败。由于存在冲突,Git无法自动解决冲突。建议你手动解决冲突并提交结果。

bash
bashgit 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")

You have unmerged paths.:有未合并的路径。

(fix conflicts and run "git commit"):建议性的消息,提示你需要解决冲突并执行git commit命令来完成合并操作。当在合并分支时,如果存在冲突(多个分支对同一部分代码进行了修改),你需要手动解决这些冲突并进行提交。

(use "git merge --abort" to abort the merge):另一个建议性的消息,提供了一个撤销合并操作的方法。如果你希望取消正在进行合并的操作,可以运行git merge --about命令。

Unmerged paths:下面的内容是未合并路劲的列表。

both modified: hello.txt:这是具体的冲突信息。它告诉你发生冲突的文件是hello.txt,并且该文件在合并过程中在两个分支都进行了修改。

no changes added to commit (use "git add" and/or "git commit -a"):没有进行任何变更的提交。如果你已经解决了冲突并确认无误,可以使用git addgit commit命令提交本地库。

6、合并分支(解决冲突)

当出现冲突时,在master分支上相应的文件里会有提示,只要进到相应文件去手动解决修改就行

bash
bashcat hello.txt 
<<<<<<< HEAD
hello git! master merge
hello git!
=======
hello git!
hello git! hot-fix merge
>>>>>>> hot-fix
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

特殊符号之间的内容是:<<<<<<< HEAD当前分支的代码 =======合并过来的代码>>>>>>> hot-fix

修改成以下内容,并提交到本地库

bash
bashcat hello.txt 
hello git! master merge
hello git! hot-fix merge
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git!
hello git! hot-fix test

git add hello.txt

#注意:此时使用 git commint 命令时不能带文件名
bashgit commit -m "merge hot-fix"
[master ac92acc] merge hot-fix

合并完成后,只会修改master分支上的内容,而hot-fix分支上的文件内容并未被修改

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

HEAD如果指向master,那么我们现在就在master分支上。

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

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

团队协作机制

团队内协作

git-base-007

跨团队协作

git-base-008

GitHub操作

登录需要3个号进行配合操作

创建远程库

登录之后点击右上角+号,点击New repository,起一个远程库名字(这个名字最好和本地的git项目名字一样),选择Public,创建。

账号远程库名字创建的别名
hubhubqqtrgit-demogit-demo
pqpqgit-demoorigin
fftyqqs…………

远程仓库操作

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

1、创建远程仓库别名

bash
bashgit remote add git-demo https://github.com/hubhubqqtr/git-demo.git

bashgit remote -v
git-demo        https://github.com/hubhubqqtr/git-demo.git (fetch)
git-demo        https://github.com/hubhubqqtr/git-demo.git (push)

2、推送本地分支到远程仓库

bash
bashgit push git-demo master
Enumerating objects: 18, done.
Counting objects: 100% (18/18), done.
Delta compression using up to 6 threads
Compressing objects: 100% (12/12), done.
Writing objects: 100% (18/18), 1.35 KiB | 1.35 MiB/s, done.
Total 18 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
To https://github.com/hubhubqqtr/git-demo.git
 * [new branch]      master -> master

使用windows,过程中会弹出“凭据管理器”进行登录账号即可。

此时在github上查看可以看到远程推送成功。

3、拉取项目

(拉取远程仓库到本地并合并整合)

先在远程库上修改文件,然后提交

git-base-009

git-base-010

bash
bashgit pull git-demo master
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 651 bytes | 8.00 KiB/s, done.
From https://github.com/hubhubqqtr/git-demo
 * branch            master     -> FETCH_HEAD
   93f06de..ff861db  master     -> git-demo/master
Updating 93f06de..ff861db
Fast-forward
 hello.txt | 1 +
 1 file changed, 1 insertion(+)

4、克隆远程仓库到本地

cd到一个新文件

bash
cd /home/ggt/pqpq

git clone https://github.com/hubhubqqtr/git-demo.git
Cloning into 'git-demo'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 21 (delta 6), reused 17 (delta 5), pack-reused 0
Receiving objects: 100% (21/21), done.
Resolving deltas: 100% (6/6), done.

cd git-demo/

git remote -v
origin  https://github.com/hubhubqqtr/git-demo.git (fetch)
origin  https://github.com/hubhubqqtr/git-demo.git (push)

git branch -v
* master ff861db 111

clone会做如下操作:拉取代码->初始化本地库->自动创建别名。

5、邀请加入团队

git-base-011

git-base-012

git-base-013

复制以上的地址后,发给pqpq用户,pqpq登录的浏览器里粘贴然后接受邀请,然后就可以看到协同的项目了。

git-base-014

pqpq可以修改内容并push到远程仓库了。

pqpq编辑项目

bash
cat hello.txt
hello git! hello atguigu! 22222
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu! master merge
hello git! hello atguigu! hot-fix merge
git pull text
git pqpq commit

git push https://github.com/hubhubqqtr/git-demo.git master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 276 bytes | 276.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/hubhubqqtr/git-demo.git
   ff861db..abf1be3  master -> master

然后在hubhubqqtr项目上就可以看到更新的项目。

git-base-015

6、拉取远程库内容

hubhubqqtr/git-demo项目里pqpq提交更新了版本,hubhubqqtr需要将项目拉取更新自己的本地库。

bash
bashgit pull git-demo master
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), 256 bytes | 2.00 KiB/s, done.
From https://github.com/hubhubqqtr/git-demo
 * branch            master     -> FETCH_HEAD
   ff861db..abf1be3  master     -> git-demo/master
Updating ff861db..abf1be3
Fast-forward
 hello.txt | 1 +
 1 file changed, 1 insertion(+)

bashcat hello.txt
hello git! hello atguigu! 22222
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu!
hello git! hello atguigu! master merge
hello git! hello atguigu! hot-fix merge
git pull text
git pqpq commit

跨团队协作

将远程仓库的地址复制发给邀请跨团队协作的人,比如fftyqqs

fftyqqs收到别人发来的链接后,比如:git-demo链接地址,然后Fork将项目叉到自己的本地仓库。

git-base-016

git-base-017

然后编辑项目,提交

git-base-018

git-base-019

git-base-020

回到hubhubqqtr账号上可以看到有一个Pull request请求。进入聊天室,可以讨论代码相关内容。

git-base-021

Write处可以和对方进行聊天,要是没有问题可以点击Merge pull request进行合并代码。

git-base-022

git-base-023

hubhubqqtr的本地上拉取更新远程仓库的内容,更新之后就可以看到hello.txt文件被更新了。

bash
bashgit branch -r
  git-demo/master

bashgit pull git-demo master
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 1.27 KiB | 8.00 KiB/s, done.
From https://github.com/hubhubqqtr/git-demo
 * branch            master     -> FETCH_HEAD
   abf1be3..7950d87  master     -> git-demo/master
Updating abf1be3..7950d87
Fast-forward
 hello.txt | 1 +
 1 file changed, 1 insertion(+)

SSH免密登录

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

git-base-024

进入用户的家目录->清理掉.ssh文件->ssh-keygen -t rsa命令生成公钥->将公钥里的内容复制到github账户上

git-base-025

git-base-026

git-base-027

接下来再往远程仓库push东西的啥时候使用SSH连接就不需要登录了。

IDEA集成Git

……

IDEA集成GitHub

……

国内代码托管中心码云Gitee

自行在gitee官网上注册账号

码云复制GitHub项目

git-base-028

自建代码托管平台GitLad

gitlab官网

gitlab-ce社区免费版,gitlab-ee企业收费版。

gitlab-ce下载链接

安装时需要结合官网教程进行安装。