文章目录
- 下载安装
- Git 配置
- config文件
- 配置用户信息
- 查看配置信息
- 工作协作流程
- git四个区
- 协作流程
- 初始化新仓库
- 检出仓库
- git clone
- git remote
- 本地存有代码进行clone
- 没有git仓库
- 已存在git仓库
- 提交与修改
- git add 及 git status
- git diff
- git commit
- git reset
- git rm
- git mv
- 查看提交历史
- git log
- git blame
- 远程操作
- git fetch && git merge
- git pull
- git push
- Git 分支管理
- 创建分支
- 列出分支
- 删除分支
- 分支合并
- 合并冲突
- Git 标签
- 创建标签
- 删除标签
- 删除本地标签
- 删除远程标签
- SSH配置
- 常规项目设置
- 工具型命令
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
下载安装
Git 各平台安装包下载地址为:http://git-scm.com/downloads
官网慢,可以用国内的windows镜像:https://npm.taobao.org/mirrors/git-for-windows/
Git 配置
config文件
Git 提供了一个叫做 git config
的工具,专门用来配置或读取相应的工作环境变量。
这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
- /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用
git config
时用--system
选项,读写的就是这个文件。看当初 Git 装在什么目录,就以此作为根目录来定位,笔者目录为 C:/Program Files/Git/etc/ 。 - ~/.gitconfig 文件:用户目录下的配置文件,只适用于该用户。若使用
git config
时用--global
选项,读写的就是这个文件。在 Windows 系统上,用户目录目录一般为 C:/Users/userName。 - 当前项目的 Git 目录中的配置文件(也就是工作目录中隐藏文件夹 .git 下 config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。
配置用户信息
配置个人的用户名称和电子邮件地址:
git config --global user.name "caoyuan"
git config --global user.email test@caoyuan.com
如果用了 --global
选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。
如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global
选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
也可以编辑 git 配置文件:
在window系统上先设置config文件默认使用notepad打开
git config core.editor notepad
git config -e
针对当前仓库 `
git config -e --global
针对当前系统登录用户所有仓库
查看配置信息
要检查已有的配置信息,可以使用 git config --list
命令。
在命令行出现 (END) 时,可以按 q
键退出
git config --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
pull.rebase=false
credential.helper=manager-core
...
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:
git config user.name
caodingshuan
工作协作流程
git四个区
- Workspace: 工作区,就是你平时电脑里存放项目代码的地方。
- Index / Stage: 暂存区,用于临时存放你的改动,一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index),保存即将提交的文件列表信息。
- Repository: 仓库区(或版本库),就是安全存放数据的位置(隐藏目录 .git),这里面有你提交的所有版本的数据。其中HEAD指向最新放入仓库的版本(指向你最后一次提交的结果)。
- Remote: 远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换。
协作流程
一般协作流程如下:
- 克隆 Git 资源作为工作目录。
- 在克隆的资源上添加或修改文件。
- 如果其他人修改了,你可以更新资源。
- 在提交前查看修改。
- 提交修改。
- 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
下图展示了 Git 的协作流程:
初始化新仓库
创建新文件夹或使用一个已经存在的目录作为 Git 仓库。打开,然后执行 git init
来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行。
在执行完成 git init
命令后,Git 仓库会生成一个 .git 隐藏目录,该目录包含了资源的所有元数据,其他的项目目录保持不变。可以使用linux命令ls -a
或者dos命令dir /a
查看。
也可以使用指定目录作为Git仓库。
git init newrepo
如果当前目录下有几个文件想要纳入版本控制,需要先用 git add
命令告诉 Git 开始对这些文件进行跟踪,然后提交:
git add *.c
git add README.md
git commit -m "初始化项目版本"
以上命令将目录下以 .c 结尾及 README.md 文件提交到本地仓库中。
在 Linux 系统中,commit 信息使用单引号('),Windows 系统,commit 信息使用双引号(")。
所以在 git bash 中
git commit -m '提交说明'
这样是可以的。在 Windows 命令行中就要使用
git commit -m "提交说明"
。
检出仓库
git clone
我们使用 git clone
从现有 Git 仓库中拷贝项目。此方式适用于本地没有项目代码情况,直接从头开始完整克隆一个代码仓库。
克隆仓库的命令格式为:
git clone <repo>
如果我们需要克隆到指定的目录,可以使用以下命令格式:
git clone <repo> <directory>
参数说明:
- repo: Git 仓库。
- directory: 本地目录。
比如,要克隆 Git 代码仓库 pinia,可以用下面的命令:
git clone https://github.com/vuejs/pinia.git
执行该命令后,会在当前目录下创建一个名为pinia的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录。
如果要自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:
git clone https://github.com/vuejs/pinia.git mypinia
git clone支持多种协议,除了 HTTP(s) 以外,还支持 SSH 、Git、本地文件协议 等,下面是一些例子。
git clone http[s]://example.com/path/repo.git
git clone ssh://example.com/path/repo.git
git clone git://example.com/path/repo.git
git clone ftp[s]://example.com/path/repo.git
git clone D:/opt/git/project.git
git clone file:///opt/git/project.git
git clone rsync://example.com/path/repo.git
执行如下命令以创建一个本地仓库的克隆版本:
git clone D:\companyproject\xxx
通常来说,https协议下载速度最快,SSH协议用于需要用户认证的场合。各种协议优劣的详细讨论请参考官方文档。
报错处理:
运行clone
命令时,报错 Could not resolve host: github.com
可以先命令行输入 ping github.com
,然后获取响应的IP,笔者这里获得的是20.205.243.166。
编辑系统文件 etc/hosts,位置为 C:\Windows\System32\drivers\etc,添加了下图语句,
20.205.243.166 github.com
重新运行,最后获取成功。
git remote
为了便于管理,Git要求每个远程主机都必须指定一个主机名。git remote
命令就用于管理主机名。
不带选项的时候,git remote
命令列出所有远程主机。
git remote
输出:origin
使用 -v
选项,可以参看远程主机的网址。
git remote -v
输出:
origin https://github.com/vuejs/pinia.git (fetch)
origin https://github.com/vuejs/pinia.git (push)
上面命令表示,当前只有一台远程主机,叫做origin
,以及它的网址。
克隆版本库的时候,所使用的远程主机自动被Git命名为origin。如果想用其他的主机名,需要用 git clone
命令的 -o
选项指定。
git clone -o pinia https://github.com/vuejs/pinia.git
cd pinia
git remote
输出:pinia
上面命令表示,克隆的时候,指定远程主机叫做 pinia。
-
git remote show [<主机名>|<主机地址>]
可以查看该主机的详细信息git remote show pinia 或 git remote show https://github.com/vuejs/pinia.git 输出: * remote pinia Fetch URL: https://github.com/vuejs/pinia.git Push URL: https://github.com/vuejs/pinia.git HEAD branch: v2 Remote branches: docs/animated-pinia tracked docs/wwads tracked feat/strict-mode tracked fix/tree-shake-devtools tracked ...
-
git remote add <主机名> <网址>
用于添加远程主机,主机名为本地的版本库git remote add origin1 https://github.com/vuejs/pinia.git git remote 输出: origin1 pinia
-
git remote rm <主机名>
命令用于删除远程主机。git remote rm origin1 git remote 输出:pinia
-
git remote rename <原主机名> <新主机名>
命令用于远程主机的改名。git remote rename pinia piniachanged 输出:Renaming remote references: 100% (11/11), done. git remote 输出:piniachanged
本地存有代码进行clone
以下两种方式的前提是需要在远程建立一个空仓库,并获取代码仓库地址。
没有git仓库
mkdir emptyrepository
cd emptyrepository
git init
echo readme>README.md
git add README.md
git commit -m "first commit" // 到这一步,本地会出现当前所在的master分支
git remote add origin https://gitee.com/caodingshuan/emptyrepository.git
git push -u origin "master"
已存在git仓库
cd existing_git_repo
git remote rm origin // 删除远程同名主机名
git remote add origin https://gitee.com/caodingshuan/emptyrepository.git
git push -u origin "master"
提交与修改
Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比。
git add 及 git status
-
git add
命令可将该文件添加到暂存区。git add file1Name file2Name ...
: 添加一个或多个文件到暂存区。git add dirName
:添加指定目录到暂存区,包括子目录。git add .
: 添加当前目录下的所有文件到暂存区。
-
git status
命令用于查看在你上次提交之后是否有对文件进行再次修改。git status -s
: 获得简短的输出结果,-s(--short缩写)
。
执行 git add
命令来添加文件:
git add file.ts render.vue
执行 git status
命令,查看项目文件的当前状态,可以看到这两个文件已经加上去了
git status
输出:
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: file.ts
new file: render.vue
Untracked files:
(use "git add <file>..." to include in what will be committed)
doc/
现在我们执行 git status -s
命令来获得简短的输出结果。
git status -s
A file.ts
A render.vue
?? doc/
我们将doc目录下的文件添加到暂存区。
git add doc
现在我们再执行 git status -s
,可以看到doc目录下的文档及子目录下的文档均添加到暂存区。
git status -s
输出:
A doc/childDoc/read2.pdf
A doc/read1.pdf
A file.ts
A render.vue
当然我们可以使用 git add .
命令来添加当前项目的所有改动文件到暂存区。
现在我们修改 file.ts 文件:
再执行一下 git status -s
git status -s
输出:
A doc/childDoc/read2.pdf
A doc/read1.pdf
AM file.ts
A render.vue
AM 状态的意思是这个文件在我们将它添加到暂存区之后又有改动。改动后我们再执行 git add .
命令将其添加到暂存区中:
git diff
git diff
命令比较文件的不同,即比较文件在工作区、暂存区、**最后一次提交(commit)**之间的不同。
git diff [file]
:工作区和暂存区的差异git diff --cached [file]
或git diff --staged [file]
:显示暂存区和上一次提交(commit)的差异git diff HEAD
:查看工作区和暂存区文件改动与上一次提交(commit)的差异git diff --stat
:显示摘要而非整个 diffgit diff [first-branch]...[last-branch]
或git diff [first-commit]...[last-commit]
:显示两(多)个分支或两(多)次提交之间的差异
我们对项目test.md文件进行修改,输入git diff
命令,对比工作区和暂存区的差异。
git diff
输出:
diff --git a/test.md b/test.md
index d800886..8020981 100644
--- a/test.md
+++ b/test.md
@@ -1 +1,3 @@
-123
+md文件修改行1
+md文件修改行2
+md文件修改行3
这时候我们输入git status
查看下文件状态
git status -s
输出:M test.md
可以看到git status
显示你上次提交更新后的更改或者写入缓存的改动, 而 git diff
一行一行地显示这些具体的改动。
输入git add .
将文件从工作区添加到暂存区,我们输入git diff --cached
命令,显示暂存区和上一次提交(commit)的差异
git add .
git diff --cached
输出:
diff --git a/test.md b/test.md
index d800886..8020981 100644
--- a/test.md
+++ b/test.md
@@ -1 +1,3 @@
-123
+md文件修改行1
+md文件修改行2
+md文件修改行3
修改项目test.js文件,输入git diff HEAD
命令查看已缓存的与未缓存的所有改动
git diff HEAD
输出:
diff --git a/test.js b/test.js
index ae064d9..e969625 100644
--- a/test.js
+++ b/test.js
@@ -1 +1,3 @@
-好人是好人
+js文件修改行1
+js文件修改行2
+js文件修改行3
diff --git a/test.md b/test.md
index d800886..8020981 100644
--- a/test.md
+++ b/test.md
@@ -1 +1,3 @@
-123
+md文件修改行1
+md文件修改行2
+md文件修改行3
我们可以输入git diff HEAD --stat
来显示摘要而非整个 diff
git diff HEAD --stat
输出;
test.js | 4 +++-
test.md | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
我们也可以对比不同分支和不同提交。
- 我们先在master分支创建branch.txt文件,文本内容为当前分支名称master,修改后提交。
- 随后我们创建sit分支,修改branch.txt文件内容为sit,随后提交。
- 最后我们创建dev分支,修改branch.txt文件内容为dev。并提交。
我们先进行分支的对比
git diff dev sit master
输出:
diff --cc branch.txt
index 5c31fb8,8b25206..9001211
--- a/branch.txt
+++ b/branch.txt
@@@ -1,1 -1,1 +1,1 @@@
- sit
-master
++dev
再进行commit hash进行对比
git diff fad3a22bad4d2d2b6784c84c16189c2615b710c0 8c17f68e8c3b9c480937e18fb9718821b3ab67aa b7846a78bd43dc3e03bd16027a4701c1c1198292
输出:
diff --cc branch.txt
index 5c31fb8,8b25206..9001211
--- a/branch.txt
+++ b/branch.txt
@@@ -1,1 -1,1 +1,1 @@@
- sit
-master
++dev
可以看到输出顺序是,最后创建的dev分支的内容与随后的分支逐个进行对比。提交(commit)对比同理。
git commit
前面我们使用 git add
命令将内容写入暂存区。现在我们使用git commit
命令将暂存区内容添加到本地仓库中。
git commit -m [message]
: 提交暂存区到本地仓库中,message
可以是一些备注信息。git commit [file1] [file2] ... -m [message]
:提交暂存区的指定文件到仓库区git commit -am [message]
:-a
参数设置修改文件后不需要执行git add
命令,直接来提交
修改项目中test.js文件,提交
git add .
git commit -m "测试1"
输出:
[master cbf85e6] 测试1
1 file changed, 1 insertion(+), 1 deletion(-)
指定test.js文件提交
git add .
git commit test.js -m "测试2"
输出:
[master d969071] 测试2
1 file changed, 1 insertion(+), 1 deletion(-)
查看下文件状态
git status
输出:
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
以上输出说明我们在最近一次提交之后,没有做任何改动,是一个 “working tree clean”,翻译过来就是干净的工作目录。
如果你觉得 git add
提交缓存的流程太过繁琐,Git 也允许你用 -a
选项跳过这一步。
git commit -am "测试3"
输出:
[master eaffe72] 测试3
1 file changed, 1 insertion(+), 1 deletion(-)
如果你没有设置 -m
选项,Git 会尝试为你打开一个编辑器以填写提交信息。
打开的文档如下,需要输入此次提交的信息
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
# modified: test.js
#
git reset
git reset [ --mixed | --soft | --hard ] [ HEAD ]
:用于回退版本,可以指定退回至某一次提交的版本。
-
--mixed
为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,并将之前修改后提交到暂存区的文件回退到工作区,且之前工作区文件内容将与回退的版本内容进行合并。git reset HEAD
或git reset
命令用于取消已缓存的内容,使其回退至工作区。也可以回退指定的缓存区文件git reset test.js
。实例:
git reset HEAD^ # 回退内容至上一个版本。 git reset c856725 # 回退到指定版本。 git reset c856725 test.js # 回退 test.js 文件到指定版本。
当命令行出现
More?
,则输入几个^
,表示回退几个版本。回退内容至特定版本后,工作区中的文件包含该特定版本之后的文件内容改动(不包含该特定版本内容改动)。
-
--soft
参数用于回退到某个版本。回退带来的改动内容将自动放置在暂存区,并进行合并。工作区文件内容不受影响。git reset --soft HEAD
实例:
git reset --soft HEAD~3 # 回退上上上一个版本
-
--hard
参数撤销工作区与暂存区中所有未提交的修改内容,并将本地文件内容回退到指定版本。git reset --hard HEAD
实例:
git reset --hard HEAD~3 # 回退上上上一个版本 git reset –hard c856725 # 回退到指定版本。 git reset --hard origin/master # 将本地的文件状态回退到和远程的一样。
注意:谨慎使用
–-hard
参数,它会删除所有未提交的内容。
HEAD 说明:
HEAD
表示当前版本
HEAD^
上一个版本
HEAD^^
上上一个版本
HEAD^^^
上上上一个版本
以此类推…
也可以使用 ~
数字表示
HEAD~0
表示当前版本
HEAD~1
上一个版本
HEAD~2
上上一个版本
HEAD~3
上上上一个版本
以此类推…
git rm
git rm
命令用于删除文件。
-
git rm <file>
:将文件从暂存区和工作区中删除。即将文件在工作区中删除,并将改动自动提交到暂存区。删除下项目中test.js文件
git rm test.js 输出:rm 'test.js'
查看下文件状态
git status 输出: On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: test.js
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项
-f
。强行从暂存区和工作区中删除修改后的 test.js 文件。即删除后,工作区文件会消失,同时暂存区会保留文件删除更改。
git rm -f test.js
-
git rm --cached <file>
:把文件从暂存区域移除,但仍然保留在当前工作目录中,换句话说,仅是从跟踪清单中删除。将提交到暂存区的test.js文件进行移除
git rm --cached test.js 输出:rm 'test.js'
查看文件状态
git status 输出: On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: test.js Untracked files: (use "git add <file>..." to include in what will be committed) test.js
-
git rm –r dirName
:可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件。进入某个目录中,执行
git rm –r *
,会删除该目录下的所有文件和子目录。
注意:如果是新创建的文件夹及文件,则需要先将文件添加到暂存区,使之在git控制之下,再添加-f
参数进行删除。
即先执行git add .
,删除目录则执行git rm -r -f dirName
,进入目录执行git rm -r -f *
则删除该目录下所有文件和子目录。
git mv
git mv
命令用于移动或重命名一个文件、目录或软连接。
git mv [file] [newfile]
:重命名文件
对test.js文件重命名为testtest.js文件
git mv test.js testtest.js
git status
输出:
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: test.js -> testtest.js
如果新文件名已经存在,但还是要重命名它,可以使用 -f
参数:
git mv -f [file] [newfile]
将testtest.js重命名为branch.txt(项目中已有文件)。则看到testtest.js文件内容覆盖到branch.txt文件,同时中间文件testtest.js被删除。从追踪关系来看,即最开始的test.js文件被删除,同时将内容覆盖到branch.txt文件。
git mv -f testtest.js branch.txt
git status
输出:
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: branch.txt
deleted: test.js
将branch.txt移动到testDoc目录下
git mv branch.txt testDoc/branch.txt
git status
输出:
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: branch.txt
renamed: test.js -> testDoc/branch.txt
查看提交历史
Git 提交历史一般常用两个命令:
- git log - 查看历史提交记录。
- git blame - 以列表形式查看指定文件的历史修改记录。
git log
在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log
命令查看。
使用 git log
命令列出历史提交记录如下:
git log
输出:
commit ccddc6af6777d9496e3d577500a6c84e5235c6bc (HEAD -> master, origin/master, origin/HEAD)
Merge: b38bc3f fad3a22
Author: caodingshuan <15639167751@163.com>
Date: Fri Apr 14 16:01:58 2023 +0800
Merge branch 'dev'
commit b38bc3f16dc04325c6c7d61b4abb297068ed936d
Author: caodingshuan <15639167751@163.com>
Date: Fri Apr 14 10:35:25 2023 +0800
'test4.js'
commit c8567255a5790da53d25b44125046be7e94e69be
Author: caodingshuan <15639167751@163.com>
Date: Fri Apr 14 10:34:50 2023 +0800
...
我们可以用 --oneline
选项来查看历史记录的简洁的版本。
git log --oneline
输出:
ccddc6a (HEAD -> master, origin/master, origin/HEAD) Merge branch 'dev'
b38bc3f 'test4.js'
c856725 'test3.js'
bed069d 'test2.js'
3164e22 'test1.js'
ac43a8f '123'
fad3a22 (origin/dev, dev) change
8c17f68 (origin/sit, sit) change
b7846a7 test
9b6ac7b (tag: 1.0.3) update test.js.
5bd63fe add test.js.
9ac5e5d (tag: 1.0.0, origin/feature_1) test
我们还可以用 --graph
选项,查看历史中什么时候出现了分支、合并。以下为相同的命令,开启了拓扑图选项:
git log --graph --oneline
输出:
* ccddc6a (HEAD -> master, origin/master, origin/HEAD) Merge branch 'dev'
|\
| * fad3a22 (origin/dev, dev) change
| * 8c17f68 (origin/sit, sit) change
* | b38bc3f 'test4.js'
* | c856725 'test3.js'
* | bed069d 'test2.js'
* | 3164e22 'test1.js'
* | ac43a8f '123'
|/
* b7846a7 test
* 9b6ac7b (tag: 1.0.3) update test.js.
* 5bd63fe add test.js.
* 9ac5e5d (tag: 1.0.0, origin/feature_1) test
现在我们可以更清楚明了地看到何时工作分叉、又何时归并。
你也可以用 --reverse
参数来逆向显示所有日志。
git log --reverse --oneline
输出:
9ac5e5d (tag: 1.0.0, origin/feature_1) test
5bd63fe add test.js.
9b6ac7b (tag: 1.0.3) update test.js.
b7846a7 test
8c17f68 (origin/sit, sit) change
fad3a22 (origin/dev, dev) change
ac43a8f '123'
3164e22 'test1.js'
bed069d 'test2.js'
c856725 'test3.js'
b38bc3f 'test4.js'
ccddc6a (HEAD -> master, origin/master, origin/HEAD) Merge branch 'dev'
如果只想查找指定用户的提交日志可以使用命令:git log --author
。
git log --author=caodingshuan --oneline -5
输出:
ccddc6a (HEAD -> master, origin/master, origin/HEAD) Merge branch 'dev'
b38bc3f 'test4.js'
c856725 'test3.js'
bed069d 'test2.js'
3164e22 'test1.js'
如果你要指定日期,可以执行几个选项:--since
和 --before
,但是你也可以用 --until
和 --after
。
例如,如果我要看 Git 项目中三周前且在四月十八日之后的所有提交,我可以执行这个(我还用了 --no-merges
选项以隐藏合并提交):
git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges
git blame
git blame
命令显示指定文件文件内容每一行最后一次修改记录,
git blame <file>
如下实例:
git blame test.js
输出:
4d5200c8 (caodingshuan 2023-04-14 16:52:02 +0800 1) export default {
4d5200c8 (caodingshuan 2023-04-14 16:52:02 +0800 2) main: 'index.js',
4d5200c8 (caodingshuan 2023-04-14 16:52:02 +0800 3) type: 'test',
4d5200c8 (caodingshuan 2023-04-14 16:52:02 +0800 4) author: 'caodingshuan'
4d5200c8 (caodingshuan 2023-04-14 16:52:02 +0800 5) }
远程操作
git fetch && git merge
git fetch
命令将某个远程主机的更新,全部取回本地,通常用来查看其他人的进程,因为它取回的代码对你本地的开发代码没有影响。抓取结果是直接送到本地版本库(Repository)。该命令执行完后需要执行 git merge
将拉取到的代码合并到你所在的任意分支。
git fetch <远程主机名> <分支名>
:默认情况下,git fetch
取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。比如,取回origin主机的master分支:git fetch origin master
。git merge <远程主机名>/<分支名>
:将更新合并到你的当前分支。所取回的更新,在本地主机上要用"远程主机名/分支名"的形式读取。比如origin主机的master,就要用origin/master读取。
接下来我们在远程项目上点击 test.js 并在线修改它。
git fetch origin
输出:
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 1.01 KiB | 6.00 KiB/s, done.
From https://gitee.com/caodingshuan/testproject
4d5200c..35f3cd0 master -> origin/master
当远程主机名只有origin
,则直接执行git fetch
接着执行
git merge origin/master
输出:
Updating 4d5200c..35f3cd0
Fast-forward
test.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
当远程更新代码分支与当前分支名称对应一致时,则可直接git merge
。如远程更新代码分支为origin/master,本地分支为master。
查看test.js文件,内容已经更改。
此外,也可以使用git rebase 主机名/分支名
命令,在本地分支上合并远程分支。
git rebase origin/master
上面命令表示在当前分支上,合并origin/master。
git pull
git pull
命令用于从远程获取代码并合并本地的版本。git pull
其实就是 git fetch
和 git merge FETCH_HEAD
的简写。
命令格式:git pull <远程主机名> <远程分支名>:<本地分支名>
将远程主机 origin 的 master 分支拉取过来,与本地的 dev 分支合并。
git pull origin master:dev
如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin master
在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone
的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动"追踪"origin/master分支。
Git也允许手动建立追踪关系。
git branch --track master origin/next
或
git branch --set-upstream-to master origin/next
上面命令指定master分支追踪origin/next分支。
如果当前分支与远程分支存在追踪关系,git pull
就可以省略远程分支名。
git pull origin
上面命令表示,本地的当前分支自动与对应的origin主机"追踪分支"(remote-tracking branch)进行合并。
如果当前分支只有一个追踪分支,连远程主机名都可以省略。
git pull
上面命令表示,当前分支自动与唯一一个追踪分支进行合并。
如果合并需要采用rebase
模式,可以使用--rebase
选项,默认为merge
模式,即会保留合并分支的提交记录,而rebase
模式则不会。
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
如果远程主机删除了某个分支,默认情况下,git pull
不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull
不知不觉删除了本地分支。
但是,你可以改变这个行为,加上参数 -p
则会在本地删除远程已经删除的分支。
注:此处删除的是本地仓库记录的远程仓库分支信息,并不会删除之前从远程仓库检出到本地的同名分支,检出的分支还需要手动删除。
git pull -p
# 等同于下面的命令
git fetch --prune origin
git fetch -p
git push
git push
命令用于从将本地的分支改动上传到远程并合并。
命令格式如下:git push <远程主机名> <本地分支名>:<远程分支名>
,如git push origin master:master
注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull
是<远程分支>:<本地分支>,而git push
是<本地分支>:<远程分支>。
git push <远程主机名> <本地分支名>
:如git push origin master
,省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。直接git push origin
。
如果当前分支与多个主机存在追踪关系,则可以使用-u
选项指定一个默认主机,这样后面就可以不加任何参数使用git push
。
git push -u origin master
上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,并将本地master分支与远程master分支建立追踪关系,后面就可以不加任何参数使用git push
了。
不带任何参数的git push
,默认只推送当前分支,这叫做simple
方式。此外,还有一种matching
方式,会推送所有有对应的远程分支的本地分支。Git 2.0版本之前,默认采用matching
方法,现在改为默认采用simple
方式。如果要修改这个设置,可以采用git config
命令。
git config --global push.default matching
# 或者
git config --global push.default simple
还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用--all
选项。
git push --all origin
上面命令表示,将所有本地分支都推送到origin主机。
如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull
合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用--force
选项。
git push --force origin
上面命令使用--force
选项,结果导致远程主机上更新的版本被覆盖。除非你很确定要这样做,否则应该尽量避免使用--force
选项。
最后,git push
不会推送标签(tag),除非使用--tags
选项。
git push origin --tags
Git 分支管理
几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。
Git 分支实际上是指向更改快照的指针。有人把 Git 的分支模型称为必杀技特性,而正是因为它,将 Git 从版本控制系统家族里区分出来。
创建分支
创建分支命令:git branch branchname
。
先创建dev分支,并查看所有分支
git branch dev
git branch -a
输出:
dev
* master
sit
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/sit
切换到dev,推送到远程,并查看所有分支
git checkout dev
输出:Switched to branch 'dev'
git push --set-upstream origin dev
输出:
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
remote: Create a pull request for 'dev' on Gitee by visiting:
remote: https://gitee.com/caodingshuan/testproject/pull/new/caodingshuan:dev...caodingshuan:master
To https://gitee.com/caodingshuan/testproject.git
* [new branch] dev -> dev
branch 'dev' set up to track 'origin/dev'.
git branch -a
输出;
* dev
master
sit
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sit
列出分支
列出分支基本命令:git branch
。没有参数时会列出你在本地的分支。
git branch
输出:
dev
* master
sit
此例的意思就是,我们有一个叫做 master 的分支,并且该分支是当前分支。当你执行 git init
的时候,默认情况下 Git 就会为你创建 master 分支。
切换分支命令:git checkout branchname
。当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的工作目录的内容,所以多个分支不需要多个目录。
当git fetch
取回远程主机的更新以后,可以在它的基础上,使用git checkout -b newBranch 主机名/分支名
命令来创建新分支并立即切换到该分支下,从而在该分支中操作。
git checkout -b newBranch origin/master
上面命令表示,在最新origin/master的基础上,创建一个新分支。
当在当前分支基础上创建新分支,则可以省略"主机名/分支"
git checkout -b newtest
输出;Switched to a new branch 'newtest'
git branch
输出:
dev
master
* newtest
sit
使用分支将工作区文件的修改区分开来,从而让我们能够在不同开发环境中做事,并来回切换。
git branch
命令的-r
选项,可以用来查看远程分支,-a
选项查看所有分支。
git branch -r
git branch -a
删除分支
删除分支命令:git branch -d branchname
删除newtest分支,并查看结果
git branch -d newtest
输出:Deleted branch newtest (was 2e3ef73).
git branch
输出:
* dev
master
sit
分支合并
一旦某分支有了独立内容,你终究会希望将它合并回到你的主分支。 你可以使用git merge
命令将任何分支合并到当前分支中去:
将dev分支合并到master分支,并删除dev分支
git merge dev
输出;
Updating 2e3ef73..f571eb1
Fast-forward
test.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
git branch -d dev
输出:Deleted branch dev (was f571eb1).
git branch
输出:
* master
sit
合并冲突
合并并不仅仅是简单的文件添加、移除的操作,Git 也会合并修改。
创建dev分支,修改test.js文件,并提交
git checkout -b dev
输出:Switched to a new branch 'dev'
// 修改test.js文件后
git diff
输出:
diff --git a/test.js b/test.js
index 1cd940e..1a8cb18 100644
--- a/test.js
+++ b/test.js
@@ -1,5 +1,5 @@
export default {
- main: 'index.js devchanged',
- type: 'test devchanged',
- author: 'caodingshuan devchanged'
+ main: 'index.js devEdit',
+ type: 'test devEdit',
+ author: 'caodingshuan devEdit'
}
git commit -am "dev修改"
[dev 719f50d] dev修改
1 file changed, 3 insertions(+), 3 deletions(-)
切换到master分支,修改test.js文件,并提交
git checkout master
输出:
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
// 修改完test.js文件
git diff
输出:
diff --git a/test.js b/test.js
index c833ee3..aaeb8d4 100644
--- a/test.js
+++ b/test.js
@@ -1,5 +1,5 @@
export default {
- main: 'index.js dev',
- type: 'test dev',
- author: 'caodingshuan dev'
+ main: 'index.js masterEdit',
+ type: 'test masterEdit',
+ author: 'caodingshuan masterEdit'
}
git commit -am "master提交"
输出:
[master 3ae6877] master提交
1 file changed, 3 insertions(+), 3 deletions(-)
git push
输出:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 348 bytes | 348.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To https://gitee.com/caodingshuan/testproject.git
2e3ef73..3ae6877 master -> master
切换到master分支,并将dev合并到master,则出现冲突
git merge dev
输出:
Auto-merging test.js
CONFLICT (content): Merge conflict in test.js
Automatic merge failed; fix conflicts and then commit the result.
git diff
输出:
diff --cc test.js
index aaeb8d4,1a8cb18..0000000
--- a/test.js
+++ b/test.js
@@@ -1,5 -1,5 +1,11 @@@
export default {
++<<<<<<< HEAD
+ main: 'index.js masterEdit',
+ type: 'test masterEdit',
+ author: 'caodingshuan masterEdit'
++=======
+ main: 'index.js devEdit',
+ type: 'test devEdit',
+ author: 'caodingshuan devEdit'
++>>>>>>> dev
}
``
手动修改冲突后,添加到暂存区,后进行提交
```cmd
git diff
输出:
diff --git a/test.js b/test.js
index aaeb8d4..1a8cb18 100644
--- a/test.js
+++ b/test.js
@@ -1,5 +1,5 @@
export default {
- main: 'index.js masterEdit',
- type: 'test masterEdit',
- author: 'caodingshuan masterEdit'
+ main: 'index.js devEdit',
+ type: 'test devEdit',
+ author: 'caodingshuan devEdit'
}
git add .
git commit -m "冲突解决"
输出:
[master d6d1c68] 冲突解决
1 file changed, 3 insertions(+), 3 deletions(-)
git push
Git 标签
创建标签
git tag <tagname>
:给最新一次(HEAD
)提交打上tagname
的标签。git tag -a <tagname>
:给最新一次(HEAD
)提交打上(打开你的编辑器)带注解的tagname
的标签。会记录这标签是什么时候打的,谁打的。git tag -a <tagname> -m "注解"
:指定标签信息命令,不会打开编辑器。
当我们执行 git log --decorate
时,我们可以看到我们的标签了。
git tag v1.0
git tag -a v1.1
输出:hint: Waiting for your editor to close the file... unix2dos: converting file D:/project/personal/testproject/.git/TAG_EDITMSG to DOS format...
dos2unix: converting file D:/project/personal/testproject/.git/TAG_EDITMSG to Unix format...
git log --decorate --oneline --graph
输出:
* d6d1c68 (HEAD -> master, tag: v1.1, tag: v1.0, origin/master, origin/HEAD) 冲突解决
* 3ae6877 master提交
* f571eb1 (origin/dev) dev提交
* 2e3ef73 'addTest'
* eafeb09 '123'
* 03e3adf 'test2'
* 7d71042 'test'
* 5fa3a21 update test.js.
* 4d5200c 'test.js'
* 52162e9 'testchanged3'
* e7176ba 'testchanged2'
* 4e5ea32 'testchanged1'
* ccddc6a Merge branch 'dev'
|\
| * fad3a22 change
| * 8c17f68 (origin/sit, sit) change
* | b38bc3f 'test4.js'
* | c856725 'test3.js'
* | bed069d 'test2.js'
* | 3164e22 'test1.js'
* | ac43a8f '123'
|/
* b7846a7 test
* 9b6ac7b update test.js.
* 5bd63fe add test.js.
* 9ac5e5d test
如果我们忘了给某个提交打标签,又将它发布了,我们可以给它追加标签。
git tag -a v0.9 2e3ef73
git log --decorate --oneline --graph
输出:
* d6d1c68 (HEAD -> master, tag: v1.1, tag: v1.0, origin/master, origin/HEAD) 冲突解决
* 3ae6877 master提交
* f571eb1 (origin/dev) dev提交
* 2e3ef73 (tag: v0.9) 'addTest'
* eafeb09 '123'
* 03e3adf 'test2'
* 7d71042 'test'
* 5fa3a21 update test.js.
* 4d5200c 'test.js'
* 52162e9 'testchanged3'
* e7176ba 'testchanged2'
* 4e5ea32 'testchanged1'
* ccddc6a Merge branch 'dev'
|\
| * fad3a22 change
| * 8c17f68 (origin/sit, sit) change
* | b38bc3f 'test4.js'
* | c856725 'test3.js'
* | bed069d 'test2.js'
* | 3164e22 'test1.js'
* | ac43a8f '123'
|/
* b7846a7 test
* 9b6ac7b update test.js.
* 5bd63fe add test.js.
* 9ac5e5d test
git tag
:查看所有标签
git tag
输出:
v0.9
v1.0
v1.1
删除标签
删除本地标签
git tag --delete tagname
:删除本地指定标签
git tag
输出:
v0.9
v1.0
v1.1
git tag --delete v0.9
输出:Deleted tag 'v0.9' (was ea32475)
git tag
输出:
v1.0
v1.1
git tag -l | xargs git tag -d
:批量删除本地所有标签,在git bash命令行工具执行。
删除远程标签
先将本地标签上传到远程,执行git push --tag
git push --tags
输出:
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 156 bytes | 156.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To https://gitee.com/caodingshuan/testproject.git
* [new tag] v1.0 -> v1.0
* [new tag] v1.1 -> v1.1
git ls-remote --tags origin
:列出远程存储库上标签
git ls-remote --tags origin
输出:
d6d1c682bbd645bba5b61e22b87b9bb5716b8f35 refs/tags/v1.0
a44f20639b6fdf6a42d01d07f96362ed91e060f2 refs/tags/v1.1
d6d1c682bbd645bba5b61e22b87b9bb5716b8f35 refs/tags/v1.1^{}
git push origin --delete tagName
:删除远程指定标签
git push origin :tagname
: 将"空"引用推送到远程指定标签,进行远程标签删除
git push origin --delete tagName1 tagNam2 tagNam3
:手动批量删除远程多个标签
git push origin --delete v1.0 或 git push origin :v1.0
输出:
remote: Powered by GITEE.COM [GNK-6.4]
To https://gitee.com/caodingshuan/testproject.git
- [deleted] v1.0
git ls-remote --tags origin
输出:
a44f20639b6fdf6a42d01d07f96362ed91e060f2 refs/tags/v1.1
d6d1c682bbd645bba5b61e22b87b9bb5716b8f35 refs/tags/v1.1^{}
git show-ref --tag | awk '{print ":" $2}' | xargs git push origin
:批量删除所有远程标签,在git bash命令行工具执行。
注意:
- 删除tag,本地与远程是分开操作的。如果想把本地以及远程的tag全部删除,两个批量删除命令分开执行即可。
- 否则本地删除,远程没有删除,则在
pull
拉取后,远程标签会同步到本地。本地没有删除,远程删除,则push --tag
时,会将本地标签同步到远程。
SSH配置
如果你本地和远程Git仓库之间的传输是通过SSH加密的,那我们需要配置验证信息。
使用SSH公钥可以让你在你的电脑和 Gitee 通讯的时候使用安全连接(Git的Remote要使用SSH地址)
使用ssh-keygen -t rsa -C "youremail"
命令生成 SSH Key。
后面的 your_email 改为你在Git仓库上注册的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行。
成功的话会在用户目录下生成 .ssh
文件夹,进去,打开 id_rsa.pub
,复制里面的内容。
ssh-keygen -t rsa -C "15639167751@163.com"
输出:
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\caodingshuan/.ssh/id_rsa): ## 直接回车
Enter passphrase (empty for no passphrase): ## 直接回车
Enter same passphrase again: ## 直接回车
Your identification has been saved in C:\Users\caodingshuan/.ssh/id_rsa.
Your public key has been saved in C:\Users\caodingshuan/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:QW48fxlTUSw72uaSFDucWoUlbe3XCv6GKunD9ahXtK0 15639167751@163.com
The key's randomart image is:
+---[RSA 3072]----+
| . .o=.|
| + ..= o|
| * o= +.|
| . + =++ +|
| S .+o@ o.|
| ..% = |
| . o B O |
| = + E + |
| .o=.. o |
+----[SHA256]-----+
回到 git 上,进入账户设置,进入SSH公钥菜单栏,将本地id_rsa.pub
文件内容粘贴到公钥输入区,标题填写当前公钥对应邮箱,方便后续成员变动进行处理。
为了验证是否成功,需要进行git地址验证:
ssh -T git@gitee.com
输出:
Warning: Permanently added the ED25519 host key for IP address '212.64.63.215' to the list of known hosts.
Hi 曹定栓! You've successfully authenticated, but GITEE.COM does not provide shell access.
以上表明已经配置成。
之前一直是通过https进行代码仓库的下载,现在使用ssh进行下载。这边第一次执行会报错,重新执行就OK了。
git clone git@gitee.com:caodingshuan/testproject.git
下载完成,进行目录,执行git remote -v
,可以看到remote地址为SSH地址
git remote -v
输出:
origin git@gitee.com:caodingshuan/sshdemo.git (fetch)
origin git@gitee.com:caodingshuan/sshdemo.git (push)
当在单独项目上添加公钥时(如果所在git管理工具有此功能的话),此时权限会受到限定:
部署公钥允许以只读的方式访问仓库,主要用于仓库在生产服务器的部署上,免去HTTP方式每次操作都要输入密码和普通SSH方式担心不小心修改仓库代码的麻烦。
部署公钥配置后的机器,只支持clone与pull等只读操作。如果您想要对仓库进行写操作,请 添加个人公钥
常规项目设置
- git不忽略文件名大小写:
git config core.ignorecase false
,默认为true,需要在项目根目录进行使用。
工具型命令
- 退出git命令行: 按
q
- 使用内建的图形化git命令行:
gitk
- 显示历史记录时,每个提交的信息只显示一行:
git config format.pretty oneline
- 交互式添加文件到暂存区:
git add -i