Git

Git相关书籍

Git-资源

Git工作流程图

Git工作流程图

命令如下

  1. clone(克隆): 从远程仓库中克隆代码到本地仓库
  2. checkout (检出):从本地仓库中检出一个仓库分支然后进行修订
  3. add(添加): 在提交前先将代码提交到暂存区
  4. commit(提交): 提交到本地仓库。本地仓库中保存修改的各个历史版本
  5. fetch (抓取) : 从远程库,抓取到本地仓库,不进行任何的合并动作,一般操作比较少。
  6. pull (拉取) : 从远程库拉到本地库,自动进行合并(merge),然后放到到工作区,相当于
    fetch+merge
  7. push(推送) : 修改完成后,需要和团队成员共享代码时,将代码推送到远程仓库

image-20220118141526543

Git安装与常用指令

  • ls/ll 查看当前目录
  • cat 查看文件内容
  • touch 创建文件
  • vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、editPlus、notPad++等其它编 辑器)

下载与安装

Windows版本

下载地址: https://git-scm.com/download

image-20220724151032727

下载完成后可以得到如下安装文件:

Git-2.20.1-64-bit.exe

双击下载的安装文件来安装Git。安装完成后在电脑桌面(也可以是其他目录)点击右键,如果能够看 到如下两个菜单则说明Git安装成功。

image-20220724151233613

备注:

Git GUI:Git提供的图形界面工具

Git Bash:Git提供的命令行工具

当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用 该用户信息

MacOS版本

先安装homebrew:Homebrew安装配置

安装git参考:https://blog.csdn.net/weixin_45406712/article/details/122283177

# 安装git
brew install git

# 是否成功
zhangxin@ZhangdeMacBook-Air ~ % git --version
git version 2.30.1 (Apple Git-130)

zhangxin@ZhangdeMacBook-Air ~ % git init
# 得到根目录
cd /Users/zhangxin/.git/

# 用户账号信息
git config --global user.name "zx20219898"
git config --global user.email "1205362172@qq.com"
git config --global credential.helper osxkeychain

# 查看配置
git config --global --list

# 生成公钥/密钥(ssh key) Git关联远端仓库时候需要提供公钥,本地保存私钥,每次与远端仓库交互时候,远端仓库会用公钥来验证交互者身份。使用以下指令生成密钥。
ssh-keygen -t rsa
# 一直回车默认,直到成功

# 查看公钥
cat .ssh/id_rsa.pub //使用cat命令查看生成的密钥


复制,打开github ,点自己头像 >> settings >> SSH and GPG keys >>New SSH key

配置token

可以 把token直接添加远程仓库链接中,这样就可以避免同一个仓库每次提交代码都要输入token了:

git remote set-url origin https://<your_token>@github.com/<USERNAME>/<REPO>.git
<your_token>:换成你自己得到的token
<USERNAME>:是你自己github的用户名
<REPO>:是你的仓库名称

# 首次设置
git remote add origin https://zx20219898:<你的token>@github.com/zx20219898/zx20219898.github.io.git

# 以后
git remote set-url origin https://<你的token>@github.com/zx20219898/zx20219898.github.io.git

git用token代替密码

git config --global core.autocrlf false

git config --global credential.helper osxkeychain

然后下次输入一次密码(用token代替)即可永久保存

基本配置

–system 全系统
–global 当前用户
–local 当前项目

设置用户信息
git config –global user.name “zhangxin”
git config –global user.email “zx@zxblog.eu.org

查看配置信息
git config –global user.name
git config –global user.email

删除配置信息
git config –global –unset user.name

为常用指令配置别名

#用于输出git提交日志
alias git-log='git log --pretty=oneline --all --graph --abbrev-commit'
#用于输出当前目录所有文件及基本信息
alias ll='ls -al'

命令形式:git log [option]
options
–all 显示所有分支
–pretty=oneline 将提交信息显示为一行
–abbrev-commit 使得输出的commitId更简短
–graph 以图的形式显示

git log –all –pretty=oneline –abbrev-commit –graph

解决GitBash乱码问题

执行git config --global core.quotepath false

${git_home}/etc/bash.bashrc 文件最后加入下面两行
export LANG="zh_CN.UTF-8"
export LC_ALL="zh_CN.UTF-8"

获取本地仓库

要使用Git对我们的代码进行版本控制,首先需要获得本地仓库

1)在电脑的任意位置创建一个空目录(例如test)作为我们的本地Git仓库

2)进入这个目录中,点击右键打开Git bash窗口

3)执行命令git init

4)如果创建成功后可在文件夹下看到隐藏的.git目录。

image-20220724151643673

基础操作指令

Git工作目录下对于文件的修改(增加、删除、更新)会存在几个状态,这些修改的状态会随着我们执行Git 的命令而发生变化。

image-20220724151738576

本章节主要讲解如何使用命令来控制这些状态之间的转换:

  1. git add (工作区 –> 暂存区)
  2. git commit (暂存区 –> 本地仓库)

查看修改的状态(status)

  • 作用:查看的修改的状态(暂存区、工作区)
  • 命令形式:git status

状态简览
git status 命令的输出十分详细,但其用语有些繁琐。如果你使用 git status -s 命令或
git status --short 命令,你将得到一种更为紧凑的格式输出。运行 git status -s ,状态报

告输出如下:

$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt

新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。

你可能注意到了 M 有两个可放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。

例如,上面的状态报告显示: README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区, lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区。

而 Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区和工作区都有该文件被修改了的记录。


查看已暂存和未暂存的修改

diff 比较文件本身 Linux命令的对比

git diff 比较暂存区和工作区(注意先后顺序)

  • - 原文件
  • + 对比的文件
  • 5,3 从第5行开始,比较3行

image-20220730082720204

image-20220730083830495

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your
PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your
change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your
patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a
PR
that highlights your work in progress (and note in the PR title that it's

git diff <commitID> 比较 本地仓库 和 工作区

git diff --cached <commitID> 比较 本地仓库 和 暂存区

git diff --cached HEAD head指向的本地仓库 和 暂存区

若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff –staged 命令。 这条命令将比对已暂存 文件与最后一次提交的文件差异(–staged和–cached是同义词)

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

请注意,git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂 存了所有更新过的文件,运行git diff后却什么也没有,就是这个原因。

像之前说的,暂存CONTRIBUTING.md后再编辑,可以使用git status查看已被暂存的修改或未被暂存的修 改。 如果我们的环境(终端输出)看起来如下:

$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: CONTRIBUTING.md
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

现在运行git diff看暂存前后的变化:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
# Starter Projects
See our [projects
list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line

然后用git diff –cached查看已经暂存起来的变化(–staged和–cached是同义词):

 $ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your
PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your
change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your
patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a
PR
that highlights your work in progress (and note in the PR title that it's

添加工作区到暂存区(add)

  • 作用:添加工作区一个或多个文件的修改到暂存区
  • 命令形式:git add 单个文件名|通配符
    将所有修改加入暂存区:git add .
  • 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要 更加合适。—Pro Git

提交暂存区到本地仓库(commit)

  • 作用:提交暂存区内容到本地仓库的当前分支
  • 命令形式:git commit -m ‘注释内容’
  • git commit -a -m 'added new benchmarks'给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存 起来一并提交,从而跳过git add步骤.

查看提交日志(git log)

  • 作用:查看提交记录
  • 命令形式:git log [option]
    • options
      • –all 显示所有分支
      • –pretty=oneline 将提交信息显示为一行
      • –abbrev-commit 使得输出的commitId更简短
      • –graph 以图的形式显示

版本回退

  • 作用:版本切换
  • 命令形式:git reset –hard commitID
    commitID 可以使用 git-log 或 git log 指令查看
  • 如何查看已经删除的记录?
    git reflog
    这个指令可以看到已经删除的提交记录

git reset --hard HEAD^^ 回退2次

git reset --hard HEAD~n 回退n次

git reset --hard har <commitID> 回退具体版本


git checkout commitID 版本穿越(游离状态)

  1. 修改后,必须提交
  2. 现在是个创建分支的好时机

添加文件至忽略列表

cd 工作目录下 vim .gitignore

一般我们总会有些文件无需纳入Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动 生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以在工作目录 中创建一个名为 .gitignore 的文件(文件名称固定),列出要忽略的文件模式。

示例

 # 忽略所有的 .a 文件 
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf

GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表, 你可以在 https://github.com/github/gitignore 找到它。

移除文件

从工作区中移除:

  1. rm 1.md

  2. 然后再运行git rm 1.md记录此次移除文件的操作

  3. 下一次提交时,该文件就不再纳入版本管理了。

如果要删除之前修改过或已经放到暂存区的文件,则必须使用 强制删除选项 -f

移动文件

$ git mv file_from file_to

其实,运行git mv就相当于运行了下面三条命令:

$ mv README.md README
$ git rm README.md
$ git add README

Git操作远程仓库

配置SSH公钥

ssh-keygen -t rsa 生成SSH公钥

cat ~/.ssh/id_rsa.pub 获取公钥

Github -> settings -> SSH and GPG keys -> New SSH Key 添加上公钥

ssh -T git@gitee.com 验证是否配置成功

添加远程仓库

此操作需要先初始化本地库git init,然后与已创建的远程库进行对接。

git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便 使用的简写:

$ 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)
  • 例如: git remote add origin git@github.com:zx20219898/blog.git

某个场景:

由于我的仓库主分支为main,所以修改本地分支也为main,git branch -m main

本地分支关联远端分支:git branch --set-upstream-to=origin/main main

报错:fatal: 当前分支 main 没有对应的上游分支。
git push --set-upstream origin main

查看远程仓库

git remote

git remote -v命令查看远程仓库地址

推送到远程仓库

git push [-f] [--set-upstream] [远端名称 [本地分支名][:远端分支名] ]

  • 如果远程分支名和本地分支名称相同,则可以只写本地分支
    git push origin master
  • -f 表示强制覆盖
  • –set-upstream 推送到远端的同时并且建立起和远端分支的关联关系。
    git push –set-upstream origin master
  • 如果当前分支已经和远端分支关联,则可以省略分支名和远端名。
    git push 将master分支推送到已关联的远端分支
    image-20220724140112366
  • git push origin <tag_name> 把当前分支上传到远端分支上
    git push origin v_dev:v_dev 指定分支push

查询远程仓库

image-20220724145527335

本地分支与远程分支的关联关系

git branch -vv

image-20220724145647783

从远程仓库克隆

git clone <仓库路径> [本地目录] 线上代码clone到本地(本地目录可以省略,会自动生成一个目录)

  • git clone -b 分支名 git@x_online.git clone-指定分支
  • git clone git@x_online.git

image-20220724150642158

从远程仓库中抓取和拉取

git fetch [remote name] [branch name] 从远程仓库中抓取

  • 抓取指令就是将仓库里的更新都抓取到本地,不会进行合并
  • 如果不指定远端名称和分支名,则抓取所有分支。

git pull [remote name] [branch name] 拉取命令

  • 拉取指令就是将远端仓库的修改拉到本地并自动进行合并,等同于fetch+merge
  • 如果不指定远端名称和分支名,则抓取所有并更新当前分支。
  • git pull origin 分支名 拉取远端到本地

image-20220724150802147

解决合并冲突

在一段时间,A、B用户修改了同一个文件,且修改了同一行位置的代码,此时会发生合并冲突。

A用户在本地修改代码后优先推送到远程仓库,此时B用户在本地修订代码,提交到本地仓库后,也需要 推送到远程仓库,此时B用户晚于A用户,故需要先拉取远程仓库的提交,经过合并后才能推送到远端分支,如下图所示。

image-20220724144202455

在B用户拉取代码时,因为A、B用户同一段时间修改了同一个文件的相同位置代码,故会发生合并冲 突。

远程分支也是分支,所以合并时冲突的解决方式也和解决本地分支冲突相同相同

删除fork的远程仓库

fork之后如何删除呢?

1、进入想要删除的资源库 (Repository),选择资源库的“Settings”,如下图:

2、进入settings页后,下拉到最下面,会看到Danger Zone™区域,如下图。

3、点击“Delete this repository”,输入repository的名称就可以删除了。

Git分支操作

查看本地分支

git branch 查看当前所在分支,加上-a查看所有

创建本地分支

git branch 分支名

切换分支

git checkout 分支名 切换分支,
git checkout -b 分支名 在一个分支的基础上,创建并切换分支
git checkout -b 分支名 origin/分支名 拉取新分支-本地没有但是线上有的分支

合并分支(merge)

git merge 某分支名称 某分支 合并入 当前分支

hotfix 合并入 master

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)

fast-forward:快进,git merge 默认此模式,会丢失分支信息
git merge --no--ff 分支名 不使用快进

删除分支

git branch -d 分支名 删除分支时,需要做各种检查
git branch -D 分支名 不做任何检查 强制删除

解决冲突

当两个分支上对文件的修改可能会存在冲突,例如同时修改了同一个文件的同一行,这时就需要手动解
决冲突,解决冲突步骤如下:

  1. 处理文件中冲突的地方
  2. 将解决完冲突的文件加入暂存区(add)
  3. 提交到仓库(commit)

冲突部分的内容处理如下所示:

开发中分支使用原则与流程

  • master (生产) 分支
    线上分支,主分支,中小规模项目作为线上运行的应用对应的分支;
  • develop(开发)分支
    是从master创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线 要求,都可以在此版本进行开发,阶段开发完成后,需要是合并到master分支,准备上线。
  • feature/xxxx分支
    从develop创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完
    成后合并到develop分支。
  • hotfix/xxxx分支,
    从master派生的分支,一般作为线上bug修复使用,修复完成后需要合并到master、test、 develop分支。
  • 还有一些其他分支,在此不再详述,例如test分支(用于代码测试)、pre分支(预上线分支)等 等。

在Idea中使用Git

在Idea中配置Git

安装好IntelliJ IDEA后,如果Git安装在默认路径下,那么idea会自动找到git的位置,如果更改了Git的安 装位置则需要手动配置下Git的路径。选择File→Settings打开设置窗口,找到Version Control下的git选 项:

image-20220724172034393

点击Test按钮,现在执行成功,配置完成

image-20220724172110836

在Idea中操作Git

创建远程仓库

初始化本地仓库

image-20220724172421268

设置远程仓库

image-20220724172506520

提交到本地仓库

image-20220724172621633

推送到远程仓库

image-20220724172657487

克隆远程仓库到本地

image-20220724172814061

创建分支

最常规的方式

image-20220724172912127

最强大的的方式

选取任一分支的基础上创建

image-20220724172949601

切换分支及其他分支相关操作

image-20220724173138950

解决冲突

  1. 执行merge或pull操作时,可能发生冲突

image-20220724173230614

  1. 冲突解决后加入暂存区 略
  2. 提交到本地仓库 略
  3. 推送到远程仓库 略

IDEA常用GIT操作入口

第一张图上的快捷入口可以基本满足开发的需求。

image-20220724173349309

附:几条铁令

  1. 切换分支前先提交本地的修改
  2. 代码及时提交,提交过了就不会丢

附:疑难问题解决

  1. windows下看不到隐藏的文件(.bashrc、.gitignore)

image-20220724173645914

  1. windows下无法创建.ignore|.bashrc文件

这里以创建 .ignore 文件为例:

  • 在git目录下打开gitbash
  • 执行指令 touch .gitignore

image-20220724173754121

附:IDEA集成GitBash作为Terminal

image-20220724173952126

Git其他操作

我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录 中。使用 –cached 选项:

  • git rm --cached README 暂存区 =》 工作区。
  • git rm命令后面可以列出文件或者目录的名字,也可以使用glob模式。比如: git rm log/\*.log

history 查看历史命令记录


删除已提交的文件
git rm <文件名>
删除后,文件被放入暂存区
git commit -m '111'


git rm 后悔

  1. git reset HEAD <文件名>
  2. git checkout -- <文件名> (注意–后面的空格)

rm -rf <文件名> 删除到工作区


git commit --amend -m '111' 修正最近一次的commit说明

image-20220725224638267


checkout 会放弃工作区


git branch -m master master 重命名


保存现场:git stashgit stash save <记录名>

  1. 建议(规范):在功能未开发完毕前,不要commit
  2. 规定(必须):在没有commit之前,不要checkout切换分支(不在同一个commit阶段)

还原现场(默认还原最近一次) :

  • git stash pop (将原来保存的删除,用于还原内容)
  • git stash apply(还原内容,不删除原保存的内容,加上git stash apply stash{0}还原指定现场)
    • 手工删除:git stash drop stash@{0}

git stash list 查看临时文件


git tag v1.0 给当前版本打标签

git tag 查看当前标签

git tag -d v1.0 删除标签

git tag -a v2.0 -m 'release Tag'


git blame 1.txt 追责

image-20220730002155682


DEBUG

解决使用git遇到的:Enter passphrase for key ‘/Users/zhangxin/.ssh/id_rsa’

创建SSH Key

ssh-keygen -t rsa -C "youremail@example.com"

在生成SSH Key时,如果不小心设置了passphrase,使用SSH协议克隆远程仓库时,在每次git pull和git push时都会提示Enter passphrase for key '/Users/zhangxiaoxue/.ssh/id_rsa',每次都要手动输入密码才能继续操作,可以在命令行输入sh-keygen -p进行重新设置,直接回车输入为空,就没有密码了。

zhangxiaoxue@MacBook-Pro learn-git % ssh-keygen -p
Enter file in which the key is (/Users/zhangxiaoxue/.ssh/id_rsa):
Enter old passphrase:
Key has comment 'sybil3904@163.com'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.