Git相关命令
一、git介绍
1、git文件系统
git是一个分布式版本管理工具(没有中央服务器),与集中式版本管理工具svn相反。空间如下分布:
Remote是远程仓库,Repository是本地仓库(版本库)。Index是暂存区,Workspace是工作区。
git管理的是修改,而不是文件。
2、git安装
下载安装不要有中文。windows下安装git完成后,在windows界面下面会有一个Git Bash和一个Git GUI。git自带一个git config
工具来帮助设置Git外观和行为的配置变量。
可以通过以下命令查看所有的配置以及他们所在的文件git config --list --show-origin
git version
返回git版本。或者git --version
3、初次运行git前的配置
安装完成后第一件事就是设置你的用户名和邮件地址,因为Git提交都会使用这些信息,会写入到你的每一次提交中,不可更改。
在命令行输入如下:来设置用户信息
git config --global user.name “you_name”
git config --global user.email “xxxxxxxxx@163.com”
# 注意使用--global后,无论在该系统上做任何事,Git都会适用于那些信息。也可以对某个仓库指定不同的用户名和邮箱。
打印当前用户信息
git config --global user.name
git config --global user.email
或者git config --global --list # 列出所有Git当时能找到的配置
可以通过以下命令查看所有的配置以及他们所在的文件git config --list --show-origin
因为git是分布式管理系统,需要用户名和邮箱作为标识。
4、git目录
工作区有一隐藏目录.git,.git不属于工作区,是版本库。包含.git文件夹的目录就是工作目录。.git就是本地版本库/本地仓库,这里面存放了很多东西,最重要的包括stage暂存区,还有第一个分支master,以及指向master的指针HEAD。
如果想向本地仓库添加文件的话,这个文件必须在工作目录下。
5、获取帮助
git help <verb>
git <verb> --help
man git-<verb>
这三种是等价的
例如:git help config
如果不需要全面的手册,只需要可用选项的快速参考,可用用-h选项来获得更简明的help输出,例如:
git add -h
6、获取Git仓库
两种方法:
- 将尚未进行版本控制的本地目录转为Git仓库
这种需要cd到目录然后执行git init
将会在下面创建一个.git子目录,该子目录包含初始化Git仓库中所有的必须文件,.git目录也叫做版本库,不要修改这个目标里面的文件,否则会把git仓库给破坏。然后进行git add ...``git commit...
等命令。 - 从其他服务器上克隆一个已存在的Git仓库,需要用到
git clone <url>
命令,这会在当前目录下创建一个名为XXX的目录,并且目录下初始化一个.git文件夹。
git clone https://github.com/libgit2/libgit2 mylibgit
这条命令会在克隆远程仓库的时候自定义本地仓库的名字。git可以支持多种协议传输。
7、认识工作区和暂存区(索引区)
暂存区一般存在在.git目录下的index文件,所以暂存区也叫做index索引区,暂存区属于版本库,如下图所示。工作目录下的文件不外乎两种状态:已跟踪和未跟踪。可以用git status
来查看哪些文件处于哪些状态。
通过git init
把一个目录变成git可以管理的仓库。
一般流程:在Repository_0目录下新建一个.txt文件,readme.txt,写入内容,这个文件目前的状态是未跟踪。
使用git add readme.txt
将其file添加到暂存区里面去,或者使用git add.
提交所有修改。这一步是对git未跟踪的目标进行跟踪。
使用git commit -m “提交readme.txt”
,可以使用git status
来查看是否有文件未提交。这时如果对readme.txt文件进行了改动,再用git status
查看会发现有change没有提交。
8、常用的git命令总结
创建仓库:git init
新增文件命令:git add file或git add .
提交文件的命令:git commit -m或git commit -a
查看工作区状况:git status -s输出精简信息
,没有-s就是更丰富的信息。
拉取合并远程分支:git fetch/git merge或git pull
查看提交记录命令:git reflog
这次相较上次修改了哪些内容:git diff
将远程仓库代码克隆到本地:git clone git地址
查看当前分支:git branch
切换分支:git checkout <branch-name>
9、忽略文件.gitignore
例如:cat .gitignore内容:
*.[oa] # 表示告诉Git忽略所有以.o或.a结尾的文件
*~ # 告诉Git忽略所有以~结尾的文件,你可能还需要忽略 log,tmp 或者 pid 目录
.gitignore中所有空行或者以#开头的行都会被Git忽略。要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(**)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等。
# 忽略所有的 .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
二、git命令详细介绍
1、git add file/. 添加工作区文件到暂存区(索引区)
先是把修改(新加的文件)添加到暂存区,比如修改了某一个文件(新加入也算),使用git status
会提示有文件已被修改,
git add 文件名
git add 文件名1 文件名2
,将修改后的文件添加到暂存区
git add.
# 把所有文件添加到暂存区,不建议
2、git commit -m\ -am
git commit -m "message"
是将暂存区内容提交到版本库
git commit -a
是将修改文件后不需要执行 git add 命令,直接来提交
例如:git commit -am
‘修改 hello.php 文件’
git commit --help
查看commit的命令选项
git commit --amend
# 文件需要改动,但是已经commit过了,不想再add和commit一次,怎么办,通过先git add
然后git commit --amend -m “add test2”
命令可以修改上一次提交的commit而不用通过新的commit进行修改文件。
3、rm、mv、ls和git rm、git mv、git ls区别
git rm
和rm
的区别:
rm
仅仅是将这个文件删除,此时这个删除操作还未添加到暂存区。此时输入git status
显示需要暂存。commit
的时候需要先add
。回退的时候直接checkout
就行。
git rm
是在删除文件的同时将删除文件操作放到暂存区中。此时输入git status
显示需要提交。提交的时候直接commit
就行。回退的时候需要先reset HEAD
然后再checkout
。
当你不小心把一个很大的日志文件或者中间文件添加到暂存区时,想让文件在暂存区删除,但是不想删除工作区文件,则用命令git rm --cached README
git rm
还可以使用glob模式。git rm log/\*.log
此命令是删除log目录下扩展名为.log的所有文件。git rm \*~
此命令是删除所有名字以~结尾的文件。
git mv
和mv
的区别:
使用git mv
重命名git mv README.md README
就相当于一下三条命令:
mv README.md README
git rm README.md
git add README
如此操作git也会意识到这是一次重命名。所以重命名最好使用git mv
。
mv file1.txt file
: 将file1文本移动到file2目录,git mv
会把移动文件操作记录下来,并自动添加到暂存区。
ls
列出所有文件,ls -lh:使人可读单位(KB,MB,GB)显示大小的长格式列表。
git ls-files
列出当前仓库中已被跟踪的文件,包括已修改、已暂存、已提交。git ls-files
查看当前本地仓库中的已跟踪的文件
git ls-files --other --exclude-standard
这将显示本地仓库中的所有文件,包括已跟踪和未跟踪的文件。
cat file
: 将文件内容打印显示
touch file
: 修改文件时间属性,不存在则创建一个空白文件
git修改本地仓库名称,直接cd…到仓库外面,然后mv Repo_0 Repo_1
,然后再进入仓库,内部内容什么都没有变化。
4、git diff 暂存区、工作区差异
直接git diff
是对所有文件。
git diff readme.txt
# 显示暂存区和工作区之间的差异,暂存区添加之前显示某个具体文件的改动,输出信息如下:
diff --git a/readme.txt b/readme.txt # 原始和修改后文件名称,a代表暂存区,b代表工作区
index a875747..ef3c494 100644 # 前两个是File indexes 100644是file mode,指普通文件
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@ # @@表示一个新的块chunk的开始,a文件中的2-4行he b文件中的2-7行产生差异
-This is a git readme test file! # -代表a文件中才有的行
\ No newline at end of file # 代表文件末
+This is a git readme test file! # +代表b文件中才有的行
+1111111
\ No newline at end of file
有一行明明一样,为什么认为有差异,通常是空格导致的
使用git diff -w
查看去除空格差异后的输出结果。
git diff [版本1:默认是staging area] [版本2:默认是working area]
git diff --cached
# 比较暂存区与最后一次提交(最新本地仓库)的差异
git diff --staged
# 比较暂存区的文件和最后一次提交的文件差异。这两条命令是一样的。–staged和–cached是一样的。
git diff HEAD
# 查看当前版本库分支中HEAD代码与工作区的区别,即版本库与工作区的区别,而不是暂存区与工作区。
5、git status
git status -s
# 输出精简的状态
git status -s -b
# 显示当前所在的分支和精简状态信息
输出的状态包括:
On branch master # 表示你当前在master分支上
Changes not staged for commit: # 表面存在文件改动不在暂存区,在工作区,可以使用git add命令将其添加到暂存区。
Untracked files: # 表明这个提示下的文件没有被追踪加入过,可以使用git add将其添加到暂存区
Changes to be committed: # 表面这个提示下的文件已经存放在暂存区,需要提交到本地库上去,执行git commit后,会把这个提示下面的所有改动都提交到本地库上面去。
Unmerged paths: # 冲突文件,需要手动处理
6、git log查看多次commit提交信息,不包含回退的
git log
查看提交commit日志:包含每次提交的版本号、作者信息、提交时间、message信息。
git log <filename>
查看特定文件的更改历史
commit a80b57ad8819c639d6f1bf1a2093e9abce7e5251 (HEAD -> master)
Author: songts <13623291709@163.com>
Date: Mon Mar 18 20:16:01 2024 +0800
添加内容33333
git log --pretty=oneline # 每次提交排成一行信息显示
a80b57ad8819c639d6f1bf1a2093e9abce7e5251 (HEAD -> master) 添加内容33333
a55204e4715efd3f1d6c89579ba55b7098b8566b 提交readme.txt
可以使用选项-p显示每次提交所引入的差异,可以使用选项-2限制显示的日志条目数量只显示最近几次提交。
git log -p -2
git log有多个选项可以帮助你找到想要的提交:例如:
--no-merge
选项表示只显示除了合并提交之外的提交。
--since="2008-10-01
选项表示只显示从2008-10-1之后的提交。
--before="2008-11-01"
选项表示只显示从2008-11-1之前的提交。
--author="Junio C"
选项表示只显示某个人的提交。
--pretty
可以以自定义的格式输出信息;例如--pretty=oneline
每条显示一行。
详细请看git-log
7、git reflog 查看提交日志,包含回退的日志
git reflog
# 获取所有commit的版本号,包含回退之前的
而git log
是不包含回退的,git reflog是把回退也算进log里面的
dccf60f (HEAD -> master) HEAD@{0}: commit: 提交readme.txt
1e9b2b3 HEAD@{1}: commit: modify readme.txt
9e00bd2 HEAD@{2}: commit: tijiao
a55204e HEAD@{3}: reset: moving to HEAD~1
a80b57a HEAD@{4}: reset: moving to HEAD~1
f96ce0a HEAD@{5}: commit: modify readme.txt
a80b57a HEAD@{6}: reset: moving to HEAD
a80b57a HEAD@{7}: reset: moving to HEAD
a80b57a HEAD@{8}: reset: moving to a80b57a
a55204e HEAD@{9}: reset: moving to HEAD^
a80b57a HEAD@{10}: commit: 添加内容33333
a55204e HEAD@{11}: commit (initial): 提交readme.txt
git reset回退之后,又想把之前的版本找回来,就可以用这种方法。
8、撤销操作 reset checkout
提交完了发现有几个文件没有添加,或者提交信息写错了,此时可以运行带有--amend
的选项来重新提交,git commit --amend
会将暂存区的文件提交。不会产生新的提交信息而是修改上次提交的信息。
8.1、撤销工作区还未add到暂存区的改动 git checkout – readme.txt
git checkout -- readme.txt
撤销还未add到暂存区的改动,即撤销对文件的修改。这是一个危险的命令,Git会用最近提交的版本覆盖掉他。也就是将某个文件恢复到最近一次提交的状态。
如果工作区和暂存区不同,那么该命令使用暂存区来替换工作区文件。如果只是在工作区修改,那么该命令会用上一次commit来替换。
情景1:工作区对readme.txt做了修改,还未添加到暂存区stage,可以使用git checkout -- readme.txt
(注意两边空格)撤销还未添加到暂存区的改动,使用暂存区内容替换工作区内容。也可以手动在工作区撤销,然后git add
情景2:工作区添加b.txt到暂存区,然后commit提交到版本库,然后我在工作区直接删除了b.txt,此时可以直接commit删除操作到版本库,或者撤销操作,从版本库中恢复b.txt到工作区。git checkout -- b.txt
8.2、撤销add某个文件到暂存区的操作 git reset HEAD file 默认mixed
git reset HEAD file
# 撤销add到暂存区/索引区的文件
8.3、软撤销
本地代码不变,git会变为commit之前的状态,撤销commit,不撤销git add.
git reset --soft HEAD~1
# 表示撤销最后一次的commit,1可以换成更早的数字。索引区和工作区内容不变
混合:
git reset --mixed HEAD^1
# 恢复版本库和索引区至上n次提交的状态,工作区不变更。
8.4、硬撤销
git reset --hard HEAD~1
# 删除工作区改动,撤销commit,撤销add.
即撤销最近一次提交并删除相应的更改
8.5、git reset相关
git reset HEAD file
# 撤销提交到暂存区/索引区的文件
git reset --soft HEAD^n
# 撤销提交到本地仓库的文件,索引区和工作区不变更。
git reset --mixed HEAD^n
# 恢复版本库和索引区至上一次提交的状态,工作区不变更。默认mixed
git reset --hard HEAD^
# 恢复当前分支的版本库、索引区和工作空间至上一次提交的状态。回退到上个版本,这时git log少一次提交commit信息,慎用!!!
git reset --hard HEAD^^
# 上上个版本
git reset --hard HEAD~100
# 前100个版本
如果发现撤销错了,想恢复回去,使用git reflog查看之前的哈希码,然后git reset --hard hashcode
三、git远程操作
1、配置远程仓库 remote
查看你已经配置的远程仓库git remote
会返回类似origin之类的远程服务器的名字,origin是默认名字
可以使用git remote -v
来显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
git remote # 列出当前仓库中已配置的远程仓库
git remote -v # 列出当前仓库中已配置的远程仓库,并显示其URL
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
添加远程仓库,指定仓库的名称和URL,将其添加到当前仓库中:git remote add <shortname> <url>
git remote add pb https://github.com/paulboone/ticgit # 添加后,列出已配置的远程仓库,会有两个,后面fetch和push。
# git remote add origin git@github.com:song4399/Repository_0.git
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 rename <old_name> <new_name> # 将已配置的远程仓库重命名。
git remote rename pb paul #是将pb重命名为paul。值得注意的是这同样也会修改你所有远程跟踪的分支名字。 那些过去引用 pb/master 的现在会引用 paul/master。
# git remote remove <remote_name> # 从当前仓库中删除指定的远程仓库。
git remote remove paul # 移除远程仓库。一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
git remote set-url <remote_name> <new_url> # 修改指定远程仓库的 URL。
git remote show <remote_name> # 显示指定远程仓库的详细信息,包括 URL 和跟踪分支。
配置远程github仓库:
本地仓库和远程仓库(github/gitlab)之间通过SSH加密,需要设置。
(1)在用户主目录下C:\Users\Username.ssh看看有没有id_rsa和id_rsa.pub两个文件,如果没有,打开命令行,输入ssh-keygen -t rsa –C youremail@example.com,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
(2)登录github,打开setting里面的SSH Keys然后Add SSH Key,填上任意title,在Key文本框里黏贴id_rsa.pub文件的内容。这就配置好了
2、从远程仓库中抓取 git fetch
该命令只会将数据下载到本地仓库,而不会合并,需要我们手动合并。没事就git fetch一下
# git fetch <remote> # 会将远程主机的全部更新取回本地。
# git fetch <remote> <branch> # 只取回特定分支的更新。例如:`git fetch origin master`
git fetch origin # 抓取远程仓库
... master -> origin/master # 说明master分支已被更新
git merge origin/master # 合并,将更新同步到本地。此时本地内容和远程一致。
git pull:
git pull = git fetch + git merge
git pull必须加上分支名字。禁止使用git pull 命令而不加任何参数,这会拉去所有的远端分支,且merge 非常耗时危险。
git pull <远程主机名> <远程分支名>:<本地分支名>
如果是远程分支与当前分支合并,则冒号后面的部分可以省略。
也就是git pull origin master
git pull <远程主机名> <远程分支名>:<本地分支名> # 如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
3、推送到远程并合并 git push <远程主机名> <本地分支名> : <远程分支名>
禁止使用git push 命令而不加任何参数,这会将本地分支都推到远端,非常危险,一般后续都要跟 origin 分支名。
如果本地分支名和远程分支名相同,则可以省略冒号后面的远程分支名。
git push <远程主机名> <本地分支名> : <远程分支名> # 远程分支如果不存在就会被创建
git push <远程主机名> <本地分支名> # 本地分支名和远程分支名相同,则可以省略冒号后面的远程分支名。远程主机名如果没有指定就默认origin
git push origin master # 将master分支推送到origin服务器上,注意你必须先抓取上游的工作后,确认没有新的推送后才能推送你的工作。
git push --force origin master # 强制推送。
git push -u origin master # -u选项就是记录了push到远端分支的默认值,这样下次想要继续push这个远端分支的时候git push就行了
git push origin # 如果本地分支已经跟远程分支建立了追踪关系,那么可以省略远程本地分支名和远程分支名。使用git branch -vv命令,可以查看本地分支跟远程分支是否存在追踪关系。
git push origin --delete <branch> # 删除远程分支!!!
第一次推送master分支时,加上-u参数,Git不但会把本地master分支内容推送到远程新的master分支,还会把本地的master分支和远程的master分支关联起来。
【注意】,如果是之前在远程仓库拉取的分支后,自己新建了一个分支,然后做了修改,现在想提交到远程仓库,但是不合并到master上,而是希望在远程仓库也创建一个同名分支,则可以先git push然后,会提示带有set-upstream的命令,执行该命令即可在远程创建同名分支。
4、分支管理branch checkout
git提交操作时,会保存一个提交对象,该提交对象会包含一个指向暂存内容快照的指针、作者姓名邮箱、提交时的输入信息以及父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象。
git init会默认创建master分支
git branch # 查看本地分支,列出本地所有分支,当前分支前面有*号。
git branch -r # 列出所有远程分支
git branch -a # 列出所有本地分支和远程分支。
git branch -d dev # 删除分支
git branch -v # 查看每个分支以及其对于的最后一次提交的信息。
git branch --merged # 查看哪些分支已经合并到当前分支,前面没有*号就可以删除了
git branch --no-merged # 查看包含未合并工作的分支。
git branch testing # 仅仅创建一个test分支,而不切换。
# 本质上只是为你创建了一个可移动的新的指针,该命令会在当前所提交的对象上创建一个指针。
# 此时该指针应该和master指向相同的提交。那么git怎么知道当前在哪个分支上,很简单使用HEAD的特殊指针指向当前所在本地分支。
# HEAD可以看作当前分支的别名
git checkout tesing # 切换到一个已存在的分支,实际上是移动HEAD
git checkout -b dev # 创建+切换到dev分支
5、合并分支 git merge
假设现在只有一个默认的 master 分支,并提交了3次,B0、B1和B2都是提交对象。HEAD不是指向提交,而是指向当前分支。而分支指向提交。
每次产生的提交对象会包含一个指向上次提交对象(父对象)的指针,所以图中B0、B1和B2之间的箭头是指针指向父对象的意思,真正的提交顺序还是B0到B1再到B2。同时 master 指针指向最新的提交B2。
此时新建一个分支dev并切换到该分支:如下:
在dev分支上工作并提交了两次:如下
合并dev和master分支:【先git checkout master
然后git merge dev
】
由于当前master分支所指向的是你提交(dev提交)的直接上游,所以Git只是简单的将master指针向前移动。即当试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么在git合并两者时,就只会简单的将指针向前推进。
这种合并没有需要解决的分歧,也叫做:快进"fast forward"。
然后你就可以删除dev分支了。使用git branch -d dev
(2)需要处理合并的情况:当新分支提交了B3,再回到master分支提交B4,这个时候再需要merge,如下:
这种情况下的合并,git会自动创建一个新的提交并指向他!!!这个被称为一次合并提交,合并提交不止一个父提交。
此时分两种情况。当master分支和dev分支的提交是对不同文件或者同一文件的不同部分进行修改,此时Git能够合并他们。此时,Git会使用两个分支末端所指的快照B3和B4以及两个分支共同祖先B2做一个三方合并。注意这里合并后,master自动commit了一次,产生了提交B5,如下:
最后合并完成,可以删除dev分支。git branch -d dev
第二种情况,是冲突!master和dev提交是对同一个文件的同一个部分进行了不同的修改,此时会合并失败,你可以在合并冲突后的任意时刻使用git status
来查看包含合并冲突而未合并(Unmerge)的文件,直接git status
,如下:
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: test-1.txt
查看文件后:
This is test-1.
update test-1.
add test-1.
<<<<<<< HEAD
test master. # ===上面是HEAD所指向的版本
=======
test dev. # ===下面是你想要合并的dev所指向的版本
>>>>>>> dev
这里 HEAD 表示所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候,是向master合并)在这个区段的上半部分(======= 的上半部分),而 dev 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如:可以删除test dev还有<<<以及=之类的
例如:修改为:
This is test-1.
update test-1.
add test-1.
test master.
test dev.
然后git add . 以及git commit -m “connection”
冲突解决,合并如下:
合并完成,可以删除dev分支。git branch -d dev
尽可能减少冲突的办法:频繁进行git fetch
6、解决冲突 git mergetool或者VScode里面直接合并冲突
该命令会为你启动一个合适的可视化合并工具,并带领你一步一步解决这些冲突:
等你退出合并工具之后,Git 会询问刚才的合并是否成功。 如果你回答是,Git 会暂存那些文件以表明冲突已解决: 你可以再次运行 git status 来确认所有的合并冲突都已被解决:
然后可以输入git commit来完成合并提交。
7、远程分支
8、变基rebase
rebase,变基,可以直接理解为改变基底。feature分支是基于master分支的B拉出来的分支,feature的基底是B。而master在B之后有新的提交,就相当于此时要用master上新的提交来作为feature分支的新基底。实际操作为把B之后feature的提交先暂存下来,然后删掉原来这些提交,再找到master的最新提交位置,把存下来的提交再接上去(接上去是逐个和新基底处理冲突的过程),如此feature分支的基底就相当于变成了M而不是原来的B了。(注意,如果master上在B以后没有新提交,那么就还是用原来的B作为基,rebase操作相当于无效,此时和git merge就基本没区别了,差异只在于git merge会多一条记录Merge操作的提交记录)
可以使用rebase命令将提交到某一分支上的所有修改都移至另一分支上,就好像重新播放一样。
例如在下面的分支结构中,你可以提取C4中引入的补丁和修改,然后在C3的基础上应用一次,
git checkout experiment
git rebase master # 找到两个分支的共同祖先,提取相应的修改,将当前分支指向目标基地master,然后将此前保存为临时文件的修改依次应用。产生一次新的提交experiment成为C3后面的,
此时再回到master上面,执行快进合并。注意要有这一步
git checkout master
git merge experiment
你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的, 但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。
四、其他内容
1、git stash隐藏工作现场
在某个分支里面使用git stash,然后可以临时去别的分支处理bug,
恢复内容:
git stash apply恢复后,stash内容并不删除,需要使用命令git stash drop来删除,git stash pop恢复的同时把stash内容删除了。
2、git tag v1 C1
v1是标签名称
C1是某次提交
用于创建标签
3、git describe
Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe
git describe命令显示离当前提交最近的标签
4、VScode git一直提交不上去
VScode git一直提交不上去:git config --global http.sslVerify "false"然后再试试
五、git submodule子模块
来源:git子模块
1、将一个已存在的remote库添加为当前仓库的子模块
git submodule add https://...
此时执行git status
会出现:
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)
new file: .gitmodules # 该配置文件保存了项目url以及与本地目录的映射。多个子模块则会有多个记录。
new file: DbConnector
默认放到与子项目仓库同名的目录中,在本例中是DbConnector,如果想要放到其他地方,在命令结尾添加一个不同的路径。
虽然DbConnector是工作目录下的一个子目录,但git还是把他当作子模块。也就是当年不在那个目录时,git不会追踪他的内容。
提交时会看到:
git commit -am 'added DbConnector module'
[master fb9093c] added DbConnector module
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 DbConnector
最后推送这些修改:git push origin master
2、克隆含有子模块的项目
当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件: 其中有 DbConnector 目录,不过是空的。
必须运行以下两个命令来拉取子模块: git submodule init
git submodule update
不过还有更简单一点的方式。 如果给git clone
命令传递--recurse-submodules
选项,它就会自动初始化并更新仓库中的每一个子模块, 包括可能存在的嵌套子模块。
如果已经克隆了项目,但是忘记了--recurse-submodules
选项,那么可以运行git submodule update --init
将 git submodule init
和 git submodule update
合并成一步。
例如执行git submodule update --init module