Git学习笔记

IC 设计中常常使用 Git 做版本控制,本篇博客记录一下 Git 的学习和理解。

Git 本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。如果在加上远程的 Git 仓库(Remote Directory)就可以分为四个工作区域。文件在这四个区域之间的转换关系如下:

  • Workspace:工作区,就是你平时存放项目代码的地方。
  • Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息。
  • local repository:本地仓库,就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本。
  • Remote repository:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换。

绝大多数时候,可以只用下面4个命令就能完成简单的 Git 操作。

git add file1 file2
git commit -m "commit message"
git pull
git push

1、git创建和连接

1.1 注册Gitee/Github

推荐使用 Gitee,网速快,中文显示。熟练后可以去 Github 上操作,自由翱翔。注册账号后添加公钥,就可以开始了~

添加公钥的视频教学:【狂神说Java】Git最新教程通俗易懂, 视频同步笔记:狂神聊Git

1.2 下载Git工具

(1)下载 Git工具,除安装位置的选项外,其他选项可以一键到底,无脑安装;

  • 官网下载 :选择最新的 64 位 Windows 版即可,下载速度超慢。
  • 镜像下载 :选择最新日期下的 Windows 版,然后选择 Git-xxxx-64-bit.exe 文件下载。(推荐)

(2)鼠标空白处点击右键可看到新增了Git选项;

  • Git GUI Here 为 Git 的图像界面,不推荐使用
  • Git Bash Here 为 Git 的命令行界面,可以在这使用 Git 或练习 Linux 命令

(3)鼠标右键点击 Git Bash Here,进入 Git 命令行界面,输入如下类似代码设置 Git。

git config --global user.name "xianyu"
git config --global user.email "xxx@qq.com"

1.3 连接仓库

在 Gitee 上点击右上角的 “➕”号新建仓库,命名“GitTest”,设置仓库地址。

(1)git clone(推荐)

不管远程仓库是不是空白的,git clone 都能适用。

(1)Windows 下鼠标右键选择“Git Bash here”进入 git 命令行。

(2)执行“git clone https://gitee.com/xianyu_IC/GitTest.git”,git 就会下载该仓库为本地目录,进入该目录就能正常进行 git 操作了。

(3)执行“ll -a”,可以看到本地目录多了个“.git”文件,表示该目录已处于被 git 版本管理的状态。

(2)git init

gitee 上新建仓库时,下面的选项勾选和不勾选是不一样的结果,如下所示:

  • 不勾选“初始化仓库”和“设置模板”,创建的是完全空白的仓库,如果用 git init,需要提交新文件后才能 git push 成功。
  • 勾选了“初始化仓库”和“设置模板”,创建的是已有文件的仓库,如果用 git init,后面需要执行 git pull --rebase origin master 后才能 git push 成功。

如果是空白仓库,那么需要为空白仓库创建第一个文件,并传到远程仓库上。

git init 
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/xianyu_IC/GitTest.git
git push -u origin master

执行“ll -a”,可以看到本地目录多了个“.git”文件,表示该目录已处于被 git 版本管理的状态。

如果不是空白仓库,自己本地仓库内容肯定和远程仓库不一样,那么 push 前需要先执行下面这条命令。

git pull --rebase origin master

这样能够把远程仓库同步到本地仓库,再执行 git push -u origin master 就能成功了。由于前面 git push 时加入了 -u 操作,即默认连接了此仓库,那么后续再有新文件需要上传,不用再敲那么长,只需要执行“git push”即可,不过仍然建议 git push 前先执行下 git pull,看看是否和远程仓库冲突。

2、git查询和比较

2.1 文件状态

Git 中的文件有 4 种状态,如下所示:

  • Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.

  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件

  • Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改

  • Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

那么首先需要学会如何查询自己的 Git 状态,使用命令 git status,如下所示:

# 查看所有文件状态
$ git status

# 查看指定文件的状态
$ git status [file1] [file2] ...

2.2 常用查询

下面几个命令是常用的查询命令,文章后面内容也会提及,这里只是简单记录。

#============================================= 暂存区
# 查看暂存区的文件列表
$ git ls-files -s
 
# 指定编号查看暂存区文件内容
$ git cat-file -p 文件编号

# 打开git gui工具查看暂存区文件内容
$ git gui
#============================================= 提交记录
# 查看提交记录
$ git log
 
# 查看提交记录,简略方式
$ git log --oneline
 
# 查看提交记录,图形方式
$ git log --graph
 
# 查看提交记录,简略+图形
$ git log --oneline --graph
 
# 查看所有提交记录和HEAD编号,包括已撤销编号
$ git reflog
#============================================= 分支
# 查询所有本地分支
$ git branch
 
# 查询所有远程分支
$ git branch -v
 
# 查询所有本地和远程的分支
$ git branch -a
#============================================= 标签
# 查询所有tag
$ git tag
 
# 查询tag详细信息
$ git show [tag]
#============================================= 别名
# 显示远程仓库所有别名,默认是origin
$ git remote
 
# 显示远程仓库所有别名和其网址
$ git remote -v

2.3 文件比较

git diff 命令可以查看文件之间的差异。

# 显示暂存区和工作区的差异
$ git diff

# 显示暂存区和上一个commit的差异
$ git diff --cached [file]

# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD

# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]

# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"

2.4 HEAD说明

进行撤销、回退、检出等操作时,经常使用到 HEAD,它只存在于仓库区,实际是一个指针,它的含义如下所示:

#查看HEAD版本号
git reflog

#当前版本
HEAD
HEAD^0
HEAD~0

#上一版本
HEAD^
HEAD^1
HEAD~
HEAD~1

#上上版本
HEAD^^
HEAD~~
HEAD~^
HEAD~2

#上n版本
HEAD~n

3、git工作区到暂存区

首先了解一下 Git 的工作区和版本库的区别:

  • 工作区(Working Directory):即是你在电脑里能看到的目录。
  • 版本库(Repository)工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

Git的版本库里存了很多东西,其中最重要的就是称为 stage(index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

3.1 git add添加

新增文件或者修改了文件,该文件都会变成 untracked状态,即未跟踪状态。将 untracked 状态的文件添加到暂存区的语法格式如下:

#添加指定文件到暂存区
git add <file1> <file2> ...

#添加指定目录到暂存区,包括子目录
git add <dir>

#添加当前目录的所有文件到暂存区
git add .

3.2 git rm删除

执行了 git add,但希望删除某个文件的添加,可以执行下面几种方式:

#删除暂存区文件,不影响工作区原文件
git rm --cached <file>

#删除暂存区文件和工作区原文件,二者必须内容一致
git rm <file>

#强制删除暂存区文件和工作区原文件,二者可以内容不一致
git rm -f <file>

3.3 git reset/restore恢复

执行 git add 添加了很多文件到暂存区,想撤销又不想动到工作区原文件,可以用 git rm 一点点删除,也可以执行 reset 或 restore。恢复暂存区其实也就是撤销 git add。

#暂存区复位,可选版本和文件,不影响工作区
git reset [HEAD] <file>

#暂存区恢复,必须指定文件,不影响工作区
git restore --staged <file>

3.4 git checkout检出

工作区修改或删除了某个文件,想要恢复成原先的文件内容,可以执行 checkout。

#从暂存区检出所有文件到工作区
git checkout .

#从暂存区检出指定文件到工作区
git checkout <file>
git restore --<file>

#从仓库区检出所有文件到暂存区和工作区
git checkout HEAD .

#从本地仓库检出指定文件到暂存区和工作区
git checkout HEAD <file>

3.5 git clean清空

 下面指令可以在工作区中,将所有未被 Git 跟踪的文件全部清空。

git clean -df

3.6 .gitignore忽略

有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等,可以在主目录下建立".gitignore"文件,此文件有如下规则:

  1. 忽略文件中的空行或以井号(#)开始的行将会被忽略。
  2. 可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,...})代表可选的字符串等。
  3. 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
  4. 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
  5. 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
#为注释
*.txt #忽略所有 .txt结尾的文件
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

更多规则请点这里

4、git暂存区到仓库区

4.1 git commit提交

通过 add 只是将文件或目录添加到了 index 暂存区,使用 commit 可以实现将暂存区的文件提交到本地仓库。

#提交暂存区到仓库区
git commit -m "commit message"

#提交暂存区的指定文件到仓库区
git commit [file1] [file2] ... -m "commit message"

#跳过add,直接提交工作区文件到仓库区,对新文件无效
git commit -am "commit message"

#提交时显示所有diff信息
git commit -v

#修订上一次提交,文件无变化则只修订提交信息
git commit --amend -m "commit message"

4.2 git reset回退

假如现在仓库区的版本为 v1、v2、v3、v4,执行 git reset 指令可以移动 HEAD 到指定的版本,例如移动到 v3。如果修改文件后重新提交,那么下一个版本会是 v5。输入 ”git log --oneline“会发现 v4 消失了,相当于 v5 是新的分支一样。其实 v4 还在,执行 ”git reflog“即可找到 v4 版本。

#仓库区的HEAD指向上一版本,不影响暂存区和工作区
git reset --soft HEAD~

#仓库区的HEAD指向上一版本,影响暂存区,不影响工作区
# --mixed可以省略
git reset [--mixed] HEAD~

#仓库区的HEAD指向上一版本,影响暂存区,影响工作区
git reset --hard HEAD~

这个操作进行”git push“时会报错,因为本地仓库HEAD指向的版本比远程仓库的要旧,可以改用“git push -f”强制推上去就行了。

4.3 git revert重交

如果不想出现这种 v4 不好找的问题,可以用指令 git revert,它会将回退的版本取出来,修改后再提交,就是对这个版本的重新提交,它不会让之前的这个版本消失,也不会让中间的某些版本消失。

#取出某个版本
git revert -n <commit_id>

#重新提交
git commit -m "commit message"

参考博客:git回滚reset、revert、四种模式,超级详细

4.4 git checkout游离

前面提到过,如果执行”git checkout [HEAD] file“可以将暂存区或仓库区文件,检出到工作区和暂存区。如果不加 file 选项,则是另一种现象。如下所示:

#HEAD游离到指定版本
git checkout HEAD~2
git checkout <commit_ID>

这时 HEAD 游离到"匿名分支",Git 界面提示现在处于 "detached HEAD" 阶段,当前的工作区和暂存区也都是那个版本的文件。我们可以在这里取出所需的文件到别的文件夹,也可以在这里做临时的实验并进行 commit 提交,但是这些提交是匿名分支的提交,不会破坏原先的提交记录,也无法进行 push。

如果需要回到正常的版本中,可以执行如下指令:

#HEAD回到master
git checkout master

如果希望这些 commit 提交变成真正的分支,可以根据 Git 界面提示,采用下面这个指令。

git checkout -b <new-branch-name>

该操作一般用于寻找之前的某个版本的文件,结束后又回去正常的分支。

参考博客:Git 图解剖析

5、git本地仓库到远程仓库

5.1 git clone克隆

git clone 可以拷贝一个 Git 仓库到本地,让自己能够查看该项目或者进行修改并提交。进入生成的目录下,里面工作区、暂存区、本地仓库区和远程仓库区的内容是一致的。

git clone [-b {tag}] [url] [本地目录名]
  • [-b {tag}] 可以指定仓库的某个分支或tag,不写则默认master分支。
  • [url] 是远程仓库地址,支持 HTTPS 协议和 SSH 协议。
  • [本地目录名] 是可选项,如果不写则默认采用 [url] 中的名称。

5.2 git fetch取出

一旦远程主机的版本库有了更新(Git术语叫做commit),需要将这些更新取回本地,这时就要用到git fetch命令。

#取回所有远程仓库的最新内容
git fetch

#取回指定仓库分支的最新内容
git fetch [远程仓库名] [分支名]

例如我和小明同时工作,小明上传了新文件,我执行 git fetch 后能把所有远程仓库的最新内容,取回的内容不会影响到工作区和暂存区,而是以匿名版本的形式存在我的本地仓库,那么我可以采用下面操作

#查询本地分支和远程分支的名称
git branch -r

#游离到取回的分支,例如 origin/master
#注意,HEAD处于游离状态
git checkout [仓库名/分支名]

#知晓更新后,可以为此新建为我本地分支
git checkout -b newBranch origin/master

#也可以回到我主分支,进行内容合并
git checkout master
git merge origin/master

#最后上传我合并后的内容
git push

5.3 git pull更新

git pull命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。

#指定远程仓库分支拉到本地分支,并合并
git pull [远程仓库] [远程分支] : [本地分支]

#如果远程仓库和分支都已建立了追踪关系
git pull

#将更新的远程仓库同步到本地
git pull --rebase

其实 git pull 命令,旧等同于 “git fetch + git merge

一般建议 git push 前先执行下 git pull,内容合并后再执行 git push。

5.4 git push推送

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

#指定本地分支推送到指定的远程仓库分支
git push [远程仓库] [本地分支] : [远程分支]

#如果远程仓库和分支都已建立了追踪关系
git push

#如果远程仓库的版本比本地仓库更新,可以强制推送
git push -f

#将标签一起推送
git push --tags

#设置默认仓库,之后可以直接git push
git push -u remote_name

5.5 git remote别名

使用了 git init 或者需要新增远程仓库时,就需要使用到 git remote 命令,它用于在远程仓库的操作,而远程仓库的默认名为 origin

#显示远程仓库所有别名,默认是origin
git remote

#显示远程仓库所有别名和其网址
git remote -v

#新增远程仓库别名并连接远程仓库
git remote add name [url]

#删除远程仓库别名
git remote rm name

#修改远程仓库别名
git remote rename old_name new_name

实际使用时,往往用于本地仓库同时关联多个远程仓库,并希望同时推送,例如同时推送到 gitee 和 github:

#add gitee
git remote add gitee git@gitee.com:xxx/test-1.git

#add github
git remote add github git@github.com:xxx/test-1.git

#git push
git push gitee master && git push github master

如果希望默认只推送到gitee上,可以执行下面指令,以后执行 git pull 时旧默认推送到该远程仓库。

#设置默认连接关系
git push -u gitee

6、git分支与合并

项目常常需要多人开发,分支的出现很好的解决了这个问题。大家往往在分支上进行自己的开发,然后合入到主分支 master 上。如下所示:

6.1 git branch分支

git branch 可以对分支进行操作,如下所示:

#======================================================= 列出分支
# 列出所有本地分支
$ git branch

# 列出所有远程分支
$ git branch -r

# 列出所有本地分支和远程分支
$ git branch -a

# 图形方式查看分支图
$ git log --gpraph --oneline
#======================================================= 新建分支
# 新建一个分支,但依然停留在当前分支
$ git branch [branch]

# 新建一个分支,并切换到该分支
$ git checkout -b [branch]

# 新建一个分支,指向指定commit
$ git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]

# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
#======================================================= 删除分支
# 删除分支,该分支已合并
$ git branch -d [branch]

# 强制删除分支,该分支未合并
$ git branch -D [branch]

# 删除远程分支
$ git push origin --delete [branch]
$ git branch -dr [remote/branch]

6.2 git checkout切换

开始我们都是在主分支 master 上,执行新建分支后,仅仅是新增了一个指针,工作区和暂存区内容是没有变的。如果要到分支上,需要采用 git checkout 命令。

# 新建一个分支,并切换到该分支
$ git checkout -b [branch]

# 切换到指定分支,并更新工作区
$ git checkout [branch]

# 切换到上一个分支
$ git checkout -

注意:

  • git checkout commit_ID/HEAD~/fetch_branch:HEAD 处于游离状态,可以新增和提交文件,但无法 push,必须新建该分支或者 merge 到主分支
  • git checkout [~] file:用于从暂存区或仓库区检出文件到工作区和暂存区。

6.3 git merge合并

某个分支内容开发完毕,需要合并到当前分支,可以用 git merge。

记住要先进入到想合并进的分支上再执行,例如先执行下 git checkout master。

# 合并指定分支到当前分支
$ git merge [branch]

# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]

# 舍弃合并过程,回到合并前状态
$ git merge --abort

如果分支上需要获取最新的master分支的文件,可以执行下面操作:

git pull origin master

6.4 git rebase变基

git rebase 类似 git merge,它将分支的起始位置添加到变基后的位置(原先分支记录隐匿,可以用git reflog找到)。git rebase 可以让项目提交历史变得非常干净整洁,它消除了git merge操作所需创建的没有必要的合并提交,造就一个线性的项目提交历史——也就是说你可以从 origin 分支的顶部开始向下查找到分支的起始点,而不会碰到任何历史分叉。不过rebase操作丢失了合并提交能够提供的上下文信息——所以你就很难知道功能分支是什么时候应用了上游分支的变更。

git rebase的命令格式如下所示,记住要先进入到想变基的分支上再执行,例如先执行下 git checkout master。

# 变基指定分支
$ git rebase [branch]

# 交互式变基,可以详细编辑提交信息
$ git rebase -i [branch]

# 放弃变基,回到变基之前状态
$ git rebade --abort

# 解决某个冲突后,继续变基进程
$ git rebase --continue

如果执行 git pull 时,远程仓库的版本更新,那么需要先merge,也可以先用下面指令同步远程仓库。

git pull --rebase

git rebase 时也会发生冲突,如果有 10 个冲突,解决第一个后需要“git add”然后执行“git rebase --continue”,然后继续解决下一个冲突,略微麻烦。

参考博客:深入理解git rebase深入理解git rebase(二)

6.5 解决冲突

如果同一个文件在两个分支上的内容不同,合并时就会报错说冲突(分支有新文件则不会报冲突),那就需要解决冲突后才能继续合并。例如 master 和 dev 分支的 file11.txt 内容不同,进行合并时出现了冲突:

之后我们处于特殊的“master|MERGING”状态,打开 file11.txt 文件,发现它是这样的:

手动修改该文件,然后重新添加和提交,就能够解决该冲突,并离开“master|MERGING”状态。

可以用下面指令查看分支合并图。

git log --graph --oneline

7、git标签

git tag 其实就是 commit 的标识符,它很简单也很常用。

#================================= 查看tag
# 列出所有tag
$ git tag

# 查看tag信息
$ git show [tagName]
#================================= 新建tag
# 新建一个tag在当前commit
$ git tag [tagName]

# 新建一个tag在指定commit
$ git tag [tagName] [commitID]

# 新建一个分支,指向某个tag
$ git checkout -b [branch] [tagName]
#================================= 提交tag
# 提交指定tag
$ git push origin [tagName]

# 提交所有tag
$ git push origin --tags
#================================= 删除tag
# 删除本地tag
$ git tag -d [tagName]

# 删除远程tag
$ git push origin :refs/tags/[tagName]

git tag 比较简单,不懂可以再去百度。

8、git图形工具

在安装 Git 的同时,你也装好了它提供的可视化工具,gitk 和 git gui

8.1 gitk使用

在命令行输入“gitk”就可以调出gitk工具了,它相当于 git log 的加强版。

#打开gitk工具
gitk

#打开gitk工具,查看所有提交记录
gitk -all

8.2 git gui使用

在命令行输入“git gui”就可以调出gui工具了,它可以方便的查看工作区和暂存区的文件和内容,也可以进行各种 git 操作。

9、git命令速查表

 

参考资料:

  1. 【狂神说Java】Git最新教程通俗易懂, 视频同步笔记:狂神聊Git
  2. 深入浅出Git教程(转载)
  3. git基础使用教程
  4. 菜鸟网-Git教程
  5. Git命令学习,过关式的学习Git命令
  6. Git大全,包含Git推荐资料和常用的Git命令,可以常常查阅。
posted @ 2021-08-01 11:09  咸鱼IC  阅读(643)  评论(0编辑  收藏  举报