什么是git
什么是分布式系统
分布的对象:计算机
系统:肯定是通过某种方式连接起来形参的系统
分布式系统:
就是计算机之间通过网络连接起来,协同工作而形参的系统就是分布式系统
git就是用来控制这些分布式系统的系统,所以叫:分布式版本控制系统
用git来干什么---(文件)版本控制
用来保存文件或者目录不同时刻的版本(被修改),以便方便恢复之前的文件
安装git:
用户信息
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
补充:(1.1) 全局变量
--global 表示全局的,即用户的配置和邮箱的配置在当前用户都有效,该配置会出现在 ~/.gitconfig 文件中,~表示当前用户的目录。
(1.2)局部变量
既然有全局的,那么肯定有局部的啊!局部的是不加 --global 的,如下:
git config user.name "username"
git config user.email "email"
局部是配置的用户名和邮箱只对当前仓库起效的,它的配置信息会在当前仓库根目录/.git/config文件下。
ssh和http都需要。
检查配置信息
用命令修改
这里演示修改本地仓库的用户名和邮箱:
git config --replace-all user.name "name"
git config --replace-all user.email "123@qq.com"
ssh生成和配置:
ssh的作用
就是文件传输时使用的协议,你也可以选择https协议,而不需要设置ssh密钥。但是每一次使用https都要输入账号和密码,而ssh协议设置好密钥之后,进行提交,获取的时候就不需要输入账户和密码了。
生成:
1,ssh-keygen -t rsa -C "你自己远程仓库的邮箱"
2,三个回车
三次回车之后会告诉你,生成的存放密钥的文件在哪:
Your identification has been saved in /home/wujingyou/.ssh/id_rsa
Your public key has been saved in /home/wujingyou/.ssh/id_rsa.pub
4,打开id_rsa.pub,复制里面所有字符,用来配置远程仓库
配置
setting-->SSH and GPG keys--->new ssh key
随便填title,粘贴复制的密钥到key,add ssh key
一个系统上只需要创建一个ssh就可以了。
git能够进行文件传输的条件
1,远程仓库名和邮箱的配置。
2,git remote 获取远程仓库。
3,同步本地仓库和远程仓库:
1》git pull peername branch
或者 2》git pull --rebase peername branch
4,能够使用ssh协议的前提一定是在远程仓库添加本地仓库的密钥。
5,如果使用你的git利用SSH去操作任何一个远程仓库,那么操作之前一定要先在远程仓库添加你的git的密钥,让你的密钥有权限。
远程仓库http和ssh协议的切换
查看git参数配置
git config --list
现在是ssh.
配置为http
git config <--global> remote.origin.url "http的url"
基本的 Git 工作流程如下:
创建版本库(仓库--repository)-- .git---git init
创建一个工作目录,进入工作目录(工作区),执行命令git init在当前工作目录下创建一个本地仓库.git
.git目录
.git是什么
本质上就是一个目录,为什么称为仓库,因为在这个仓库里保存所有我们需要进行版本管理的文件
我们在工作目录进行文件的操作(修改,删除等),然后再将这些文件
放入(add)暂存区,再提交到本地仓库(.git目录),如果有需要,再推送到远程仓库。
为什么git init之后,git branch查看不到任何分支
git init的两个作用
1,创建版本库;
2,创建master分支;
但是此时的本地仓库没有和远程仓库关联起来,所以git branch查看不到任何分支。
所以当我们创建仓库之后,需要git pull远程仓库使本地仓库和远程仓库关联起来。
工作目录
就是我们git init生成.git目录的目录,在这个目录对文件进行操作。就是我们工作的目录。
注意不是.git仓库目录。
输出工作目录(仓库根目录)所在目录路径的命令
git rev-parse --show-toplevel
不进行git init可以git remote吗
不行。在 Git 中,Git 仓库是一个专门的目录,需要通过 `git init` 命令来初始化并创建。通过 `git init` 命令可以将当前目录初始化为一个 Git 仓库,然后才能使用 `git remote` 命令来管理远程仓库的连接和操作。
如果您在一个非 Git 仓库的目录下直接执行 `git remote` 命令,会收到错误提示 "Not a git repository"。这是因为 Git 不知道当前目录是否运行在 Git 仓库中,因为没有初始化过 Git 仓库,因此无法管理远程仓库。
因此,要使用 `git remote` 命令,需要首先在 Git 仓库中执行 `git init` 命令来创建 Git 仓库,并使用 `git remote` 命令来添加和管理远程仓库的连接和操作。
暂存区(index,stage)
什么是暂存区:
暂存区实质上是一个在.git仓库中的index文件
暂存区存在的意义
为什么需要暂存区,直接从工作目录提交到本地仓库不就好了:
有些朋友感觉暂存区多余,其实并非如此,通过这个过渡性区域可以使提交更加条理,避免无用琐碎提交。
举个比较生活化的例子,需要将一车放置杂乱无章的各类货物有序的放入仓库,最好的办法是将货物先有条理的整理到仓库门口空地上,这个空地相当于暂存区,然后再将货物用叉车运到仓库。还有一个作用就是可以更加方便的对文件进行版本管理,比如版本的回溯
.git内部:
本地仓库
什么是本地仓库
查看远程仓库
git remote show origin(远程仓库在本地的链接)
添加远程仓库:
作用(意义):
1,将远程仓库在本地建立一个简单的使用链接标识
2,可以简单的实现本地仓库和远程创库的信息互交
两种方式:
1,使用http协议
git remote add name url(http)
2,使用ssh协议:
git remote add peername url(ssh,code中可见)
peername:是你可以随便给远程仓库取的别名,你可以通过这个别名直接操作,访问远程仓库
clone和添加远程仓库的区别:
1,clone会通过网络访问远程仓库,然后复制(clone)远程仓库的数据和分支到本地仓库,在本地创建一个和远程仓库一样的仓库,添加只是把远程仓库的URL链接在本地做一个标识,以供使用,不通过网络访问远程仓库,也不创建仓库。
2,remote不会创建目录,需要自己创建属于这个仓库的工作目录。
注意:
1,自己创建一个目录用于和新的远程仓库工作时,进入这个目录,因为这个目录是空的,不是clone的,所以只是普通目录,而不是工作目录,因为没有git init初始化为工作目录,所以即使我们fetch或者创建文件或者目录,都没有版本库(.git)来进行管理。这个时候,这个目录以及其中的数据(文件和目录)就会交给上级父目录或者更上级的拥有版本库(.git)的版本库管理。所以,要记得创建工作目录时一定要git init。
查看远程仓库的命令:
git remote
重命名远程仓库在本地的链接标识:
git remote rename oldpeername newpeername
移除远程仓库在本地的链接标识:
git remote rm peername
从远程仓库获取资源:
添加远程创库之后就可以拉取远程仓库中有但本地仓库没有的信息,可以运行
git fetch peername
获取git 仓库的两种方法:
1,在现有工作目录下初始化本地仓库:
运行git init 就可以在本工作目录创建. git 仓库以供使用
.git就是本地仓库/版本库,
工作区:
本地工作目录
暂存区:
本地仓库中的一个叫index或者stage的文件
2,克隆远程仓库:
克隆仓库的命令:
1,git clone url
2,git clone url 本地仓库名
第一种情况克隆所得目录和远程仓库同名
url是要克隆的仓库的网址(可以使用https协议,也可以用ssh协议),https比较麻烦,还要用户名,密码,还要配置还令牌。
你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。
使用以上命令时git会默认生成一个指向你clone的远程仓库的标签——origin
可以通过这个标签代替url来获取远程仓库文件和push文件给远程仓库。
如果不在url之后给出clone的仓库的名称,则clone到本地的仓库与远程仓库同名
克隆远程仓库的作用
(这也是获取远程仓库文件,别人的文件的方式)
克隆将获取所有文件。
git clone (http)
网络代理导致的各种git错误
Failed to connect to 127.0.0.1 port 1080: Connection refused
如果是访问github的仓库,可能是因为网络代理(--clash)没有开。
Connection timed out after 12312 milliseconds
如果代理开了,出现这个问题,就是不能上网的意思,检查网络。
以上所有问题只需要关闭代理即可:
1,查看系统网络代理:
env | grep -i proxy
2,unset 关闭后面四个代理(git的时候指定是哪个代理的端口有问题就关闭哪个):
unset http_proxy https_proxy ALL_PROXY all_proxy
3,重启终端或运行以下命令,使更改生效:
source ~/.bashrc
4,再次查看网络代理:
env | grep -i proxy
注意:这个关闭只是临时的,只是在当前终端有效。
正确的关闭代理的方式
只需要关闭掉clash代理文件,之后开启的终端自然不会再有代理。
gnutls_handshake() failed: Error in the pull function.
TLS或者SSL握手问题。
同上:
1,关闭clash代理文件;
2,关闭代理配置。
3,从新打开新的终端。
怎样获取SSH网址
ssh,code中可见
git add
工作目录中的文件不外乎三种状态:已跟踪和未跟踪,未暂存。
已跟踪的文件:git add 成功加入暂存区的文件
未跟踪的文件:没有git add 的新文件
修改已跟踪的文件:被修改之后的文件,在git的记录中就不再在暂存区了,所以需要在此git add 加入。
(凡是用git进行管理的文件,对其进行修改之后,修改之后的文件就是一个新的文件对象,必须要从新加入仓库)
使用git diff /git diff 文件名 可以查看文件被修改的地方,linux中绿色字体是被改变的内容(增加,减少,改动)
如果要向本地仓库添加文件,这个文件必须在这个仓库的工作目录下
向本地仓库添加文件:
看图可知:
第一步:git add 文件名
第二步:git commit 文件名
注意,用git commit 提交文件到仓库时,日志是必须要写的,否则提交不了,就是-m " "。
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
提交之后,暂存区就没有内容了
git add -A 添加所有变化
git add -u 添加被修改(modified)和被删除(deleted)文件,不包括新文件(new)
git add . 添加新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
刚创建的创库可能git add .会有错误,直接git add 文件名
如何添加空目录
git中add不了空目录,但是我们可以在空目录中设置----- .gitignore文件。
让空目录不空
如何取消放入暂存区的文件
git reset HEAD 文件名
是如何知道文件添加给哪一个本地仓库:
提交之后系统会告诉你由哪个分支提交到哪一个仓库
对已加入本地仓库的文件进行修改之后:
git commit
每一次commit都会产生一个新的blob提交节点。
修改commit
有时候不想产生新的节点,指向修改上一次提交的日志。
git commit --amend
撤销commit
git push
刚创建的分支第一次推送需要指定上游:git push -u peername branch
peername可以是ssh生成的,也可以是http生成的
-u的用法,加了参数-u后,以后即可直接用git push代替git push origin master
也可以不加-u---upstream(上游)---设置本地这个当前分支和远程分支的关联关系,以后要推送当前分支到远程的这个分支,就不需要指定了。
注意:很多网上的文章说git push -u origin master是指定本地master分支和远程origin仓库的master分支的对应关系,其实不对,不一定就是本地master,而是当前分支。
1,git push---默认只推送当前分支
2,git push -u origin master
3,git push origin master
不建立分支关系,只传递
推送到远程创库和提交的区别:
提交只是将文件从本地暂存区提交到本地仓库
推送到远程仓库才会让文件被送到远程仓库
而文件被推送之前一定要先被提交
撤销push
1,回退到指定节点即可
soft,mixed和hard
- `--soft` 模式:不会修改工作区的文件,只会将 HEAD 和分支指针移动到指定的 commit 处。
- `--mixed` 模式:将 HEAD 和分支指针移动到指定的 commit 处,并清空暂存区。
- `--hard` 模式:将 HEAD、分支指针和工作区都恢复到指定的 commit 处,这个模式会删除已有的修改和 commit。慎用!
参数soft指的是:保留当前工作区,以便重新提交,比如我们这次是修改后重新提交。
也就是soft会删除回退到的节点之前的后的多余节点,但是修改的内容会被保留下来,处于放在暂存区状态。
hard:会撤销相应工作区的修改,一定要谨慎使用,以免出错。
也就是节点删除,修改也撤销。
2,撤销push,将当前节点的修改用上一个节点提交(amend)
相当于当前节点多余生成,需要撤销,然后将当前节点的修改使用上一个节点提交。
(1)git reset --soft "commit_id"
(2)git push --force
git pull:
git pull用法:
git pull命令的作用是:取回远程主机某个分支的更新(就是这个分支有,而你没有的),再与本地的指定分支合并。
一句话总结git pull和git fetch的区别:git pull = git fetch + git merge
git fetch不会进行合并执行后需要手动执行git merge合并分支,而git pull拉取远程分之后直接与本地分支进行合并。更准确地说,git pull使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。
基本用法:
git pull <远程主机名> <远程分支名>:<本地分支名>
1
例如执行下面语句:
git pull origin master:brantest
1
将远程主机origin的master分支拉取过来,与本地的brantest分支合并。
后面的冒号可以省略:
git pull origin master
表示将远程origin主机的master分支拉取过来和本地的当前分支进行合并。
注意:如果远程主机名之后只有一个分支,那是远程的分支,而本地的分支是当前工作的分支
git fetch
有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
刚创建的目录中git fetch
为什么当你创建一个目录,没有git init,也没有创建分支时,git fetch之后什么都没有。
没有git init,没有本地仓库,fetch过来的数据没有地方存放。
git push发生错误:
原因:是因为我们的本地仓库,与远程仓库的内容不一致导致的。为此在我向远程库推送的时候,要先进行pull,让本地新建的库和远程库进行同步,保持一致。
解决:
1,git pull peername branch
2,git pull --rebase peername branch
第一种方法如果不行,报错:
就使用第二种方法
git pull拉去后怎么解决冲突
什么是拉去后的冲突
本地和远程都有修改,怎么拉取和合并
先藏匿自己的修改---再拉取---显示修改---修改冲突--提交--推送
拉取后,本地和远程都有修改,但是没有合并怎么办
git stash 自己的修改;
git merge origin(git merge origin/<branch_name>);合并远程分支的修改
git stash apply
如果有冲突---修改冲突。
没有的话git stash apply会自动合并;
再次提交推送。
git stash
查看储藏的历史
git stash list
git stash apply
1,apply之后没有stash@{n},表示应用第一条储藏;
2,apply后指定应用哪一条储藏:
git stash apply stash@{1}
git reset
1,回退到指定节点即可
git reset --hard HEAD
HEAD标识当前已经提交的节点。
作用:如果你在当前节点做了修改,但是都不想要了,都删除,可以使用这个命令。
有时候,我们在错误的目录cmake .. ,导致当前目录下的文件都被删除了,可以使用这个命令恢复当前节点的数据。
git文件删除:
1,删除工作目录的文件
rm filename
删除工作目录的文件,会对
2,删除版本库文件:
git rm filename
从版本库删除的同时也从工作目录删除了
3,删除暂存区文件:
git rm --cached filename
作用:从暂存区删除,但还在工作目录
4,撤销提交
文件还原(撤销):
git文件版本还原:
git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
git checkout-- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,
文件add的时候就会产生版本。不同次的add就会产生不同的版本。
取消暂存(从暂存区撤出)
git reset HEAD filename
把添加到暂存区的文件撤回到工作区
git clean
git clean -f -n .
忽略文件
.gitignore文件
1,.gitgnore设置在哪里
2,.gitignore是不是只能有一个
3,.gitignore怎么设置
1,.gitgnore设置在哪里
在工作目录设置一个就可以了
(其他目录下也可以设置)
2,.gitignore是不是只能有一个
3,.gitignore怎么设置
.gitignore文件是用来告诉Git哪些文件和目录不需要被跟踪和纳入版本控制的,具体的写法如下:
#忽略所有的.class 文件 *.class
#_忽略所有以tmp开头的文件夹 tmp*/
#忽略所有的.log文件 *.log
#忽略.idea文件夹及其子目录和所有文件 .idea/
#忽略.idea文件夹及其子目录和所有文件 .idea/*
#忽略所有的编译输出文件 build/
#忽略所有的 DS_Store 文件 **/.DS_Store
#忽略指定文件或文件夹, 例如ignore.txt或my_folder/ignore.txt
my_folder/
注意:
1,需要或略的文件必须要在add暂存之前写入.gitignore文件,如果是在add之后再写入.gitignore文件无用。
2,每条规则占用一行,以“#”开头的为注释行。其中,“*”代表任意数量的字符,“?”代表任意一个字符,“/**/”代表匹配任意数量的子目录。
git分支
Git分支:
git保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照(想象一下,给一张桌子拍一张照片,纪录了桌子上所有物品的位置、状态,这样就可以称之为快照了。
我们不必存储所有的物品,只需存储这个照片就可以了,下一次想恢复以前的状态的时候,只需要翻出当时的那张照片,再把物品按照那张照片里的位置摆放一下就OK了。)
快照,就是一个文件在不同时刻的状态。
记录不同时刻的快照,就是记录文件不同时刻的状态
什么是分支
想要知道什么是分支,必须先知道什么是提交对象(提交节点),因为分支就是一个指向提交对象的指针。
提交对象:每一次对文件进行提交(commit)时,git都会产生一个提交对象,并保存这个提交对象。该提交对象包含一个指向文件在暂存区的快照的指针,除此之外,该提交对象还包含很多信息。
每一次产生的提交对象都包含上一次的分支(指针)
默认情况下,执行git init 时,自动生成一个分支master
分支的创建:
git branch 分支名
当前创建的分支指向当前对象
创建分支时 并不会切换到创建的分支
在执行提交之后,即产生节点之后才可以创建分支
创建的分支指向哪个提交对象
当前提交对象
创建的创库git branch不显示分支
Git 又是怎么知道当前在哪一个分支上呢?
用户可以利用HEAD指针指向其他分支,到其他分支进行操作。
分支切换的命令:
git checkout 分支名
检查分支指向的命令:
git log --oneline -- decorate
创建分支并进入:
git checkout -b 分支名
新建的分支会随着工作的进展不断向前推进(不断指向向新的提交对象),而原来的分支不动
当切换分支时,git会重置工作目录,使工作目录进入到需要进入的分支最后一次提交时的状态。
分支合并:
git merge bran1 (合并当前分支和bran1分支)
分支合并有两种情况:
1、当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支(不能往回走),那么Git在合并两者的时候,只会简单的将指针向前推进(指针右移) ,因为这种情况下的合并操作没有需要解决的分歧--这就叫做"快进(ast-forward) "。
2、第二种就是不能一路走下去可以遇到的,git会进行三方合并工作。
删除分支
git branch -d 分支名
git branch -D 分支名 //强制删除
重命名分支名
1,重命名当前分支:
git branch -m new_name;
2,重命名指定分支:
git branch -m old_name new_name
为远程仓库创建分支
创建并检出到新的分支,将新的分支推送到远程仓库即可。
git push -u oringin dev
同
git push --set-upstream origin dev
删除远程仓库的分支
git push origin :要删除的远程分支名
注意:冒号前面的本地分支为空;
git push origin :test
这条命令表示将空的本地分支推送到远端的"test"分支,从而删除该分支
smargit删除远程分支
需要切换到其他分支,界面右键删除分支
git branch -r如果查看远程有哪些分支
git branch -r
远程仓库删除分支后,其他仓库要重新拉取合并,才能保持和远程仓库一致。
git branch -v--查看本地分支和远程分支提交节点是否一致
这个没有远程分支名。
git branch -vv--查看本地分支和远程分支提交节点是否一致
这个有远程分支名。
eg:
* master 70891b75 [origin/master: 领先 3,落后 3] fix: fix error
70891b75和fix: fix error是当前master分支的commit_id和commit日志。
终端目录显示分支设置
vi ~/.bashrc
# 终端显示当前git分支名称
parse_git_branch() {
git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
source ./bashrc
该函数名为 `parse_git_branch()`,它使用 Git 命令获取当前分支的名称并将其显示在圆括号中,使其可以附加在您的终端提示符中。
解释如下:
- `git branch 2>/dev/null` 命令获取当前 Git 仓库的分支列表,`2>/dev/null` 表示将任何错误输出重定向到 `/dev/null`,以避免在没有 Git 仓库时显示错误消息。
- `sed -e '/^[^*]/d'` 命令删除不包含星号的所有行,因为星号表示当前分支。
- `sed -e 's/* \(.*\)/ (\1)/'` 命令将星号和分支名称包含在圆括号中并返回该字符串。
分支合并
1,git merge branch1;
brach1是需要和当前分支合并的分支。
2,git merge branch2 branch1;
branch2是当前分支,branch1是需要合并的分支。
git merge----合并 git rebase----变基
merge会在当前分支创建一个新提交节点,用来合并两个分支最后的提交节点。
rebase会通过“变基”把其他分支的最后的提交节点作为当前分支的起始节点,重新生成一遍当前分支的所有节点。
rebase会修改当前分支的历史。
合并,变基的本质是什么
合并
我们两个一起合并成为新的一个;
变基
你别动,我在你的基础上改变就行;
区别
合并
1,合并是要合并到当前分支;,
2,
变基
1,将当前分支变到别的分支
2,
会产生什么影响
什么情况使用合并
什么情况使用变基
查看分支指向那个对象:
获取当前 git 仓库所在的分支名称
git symbolic-ref --short -q HEAD 的作用是获取当前 git 仓库所在的分支名称。
具体作用如下:
- symbolic-ref:用于查询、修改 Git 仓库中的符号引用。
- --short:获取分支名称时,指定显示的名称为短名称。
- -q:将查询命令的错误信息输出关闭或降为警告提示,让命令更加安静,其结果将不会在输出中出现。
- HEAD:Git 中的 HEAD 是指向当前分支的引用,因此 symbolic-ref 命令带上 HEAD 参数就是指查询当前所在的分支。
因此,执行 git symbolic-ref --short -q HEAD 命令,如果输出不为空,则表示当前所在的分支。如果出现错误,则不会有任何输出。该命令在编写 Git 命令脚本时经常用到。
快进(合并)
没有产生分叉,前进合并就可以。
git合并时没有分叉就选择快进。
查看与当前分支合并或者没有合并的其他分支
查看已经合并的分支
git branch --merge
这个命令输出当前分支的所有直接上游分支,也就是没有分叉的分支。
注意:不是只输出指向同一个节点的分支,而是一条节点线上的所有分支。
查看未合并的分支
git branch --no-merge
查看和当前分支分叉的分支。
查看文件是否合并状态
git status
unmerged:文件名
就是未合并
merged:文件名就是已经合并的。
HEAD
单独一个HEAD
eg:git diff HEAD
表示当前结点。
HEAD~
HEAD~只处理当前分支。
注意:master分支的上一个结点是tmp分支的所在的结点fc11b74, 79f109e才是master的第二个父节点。
HEAD~
当前结点的父节点。
HEAD~1
当前结点的父节点。
HEAD~n
当前结点索引为0,n为当前结点之后的第n个结点。
HEAD^n
这个是用来处理一个由多个分支合并而来的结点和他的各个第一级父节点之间的关系的命名。
查看git diff的案例。
git rebase -i HEAD~n
作用:变基(合并)当前结点到当前结点之前的第n个父亲结点,索引从1开始。
`-i` 参数是 `--interactive` 的缩写,表示我们要进行交互式变基。交互式变基是一种在变基操作的同时对提交历史进行编辑的方法,通常用于合并、压缩、移除提交等操作。
git rebase虽然用于合并提交,但是本质上是变基。
git rebase -i HEAD~n
指定需要可以变基合并的所有结点,索引从1开始。
注意:merge的结点计算入内。
在交互式界面中会列出所有选择的结点commit id,最下面是第一个结点,我们可以往上选择删除结点,保留我们需要保留的基结点。
git rebase -i HEAD~
同git rebase -i HEAD~1。
git rebase -i HEAD~4
变基前:
目的:以11111作为基结点,合并前面三个结点。
所以-i 交互界面中,保留tmp和1111,其他的删除。
变基后:
原则:以谁作为基结点进行变基,就~指定到谁的索引,索引从1开始。
注意:基结点不会变,合并后被保留,只是集结点之前的结点被合并。
交互模式下:如果不删除任何结点,那么就表示以第二结点为基结点,重新生成第一个结点。
不删除任何结点:
没有任何变化。
git reset和git rebase的异同
相同点:都可以用于合并结点。
不同点:git reset 回退到旧结点。git rebase 会合并生成新的结点。
git diff
git diff 文件名
查看这个文件工作区和暂存区的区别。
git diff --cached 文件名
查看这个文件暂存区和已经提交的当前结点的区别。
git diff HEAD
查看当前结点工作区和暂存区的区别。
git diff --cached HEAD
查看当前结点暂存区和提交的区别。
git diff HEAD^1
查看当前结点(目标结点)和第一级父节点之间的区别。
git diff HEAD^2
查看当前结点和第二级父节点之间的区别。
git diff HEAD^n
HEAD^n都是表示当前结点至少由n个分支合并而来,如果n超过了来源分支的数量,则:
git冲突
冲突的不同部分含义
在 Git 中,当合并代码时出现冲突,Git 会在冲突的文件中添加一些特定的标记以表示冲突的位置。在 Git 中,`<<<<<<`、`======` 和 `>>>>>>` 之间的内容就是这些特殊标记。
具体来说,`<<<<<<<< HEAD` 代表的是当前本地分支的修改,`=======` 代表的是本次合并的分界线,同时也代表冲突的位置,`>>>>>>> <branch>` 代表的是要合并的远程分支的修改。其中,`<branch>` 表示远程分支的名字。
例如,在下面的示例中,表示的是冲突文件的两个修改分别来自当前本地分支和要合并的远程分支:
<<<<<<< HEAD
This is the code in the current local branch
=======
This is the code in the remote branch
>>>>>>> remote_branch
解决冲突代码之后应该怎么做
需要暂存起来,即git add 。
如果不需要修改,则继续提交。
没有指定分支冲突解决办法pull时的错误
Need to specify how to reconcile divergent branches.
smartgit合并冲突可以直接在界面合并,也可以打开文件合并;
合并完成之后选中冲突的文件之后要暂存;
smartgit拉取远程仓库的分支
电机远程的分支检出,如果本地没有这个远程分支,就会显示是否创建这个分支。
如何删除远程仓库的文件
github上只能删除仓库,不能删除文件和目录。
删除文件和目录用命令:
1,删除远程仓库,保留本地在
git pull 远程仓库名 分支
dir
git rm -r --cached 要删除的文件或者目录
git commit -m '.....'
git push -u 远程仓库名 分支
2,本地和远程仓库都删除
git log
git log查看commit信息
查看提交历史:
git log
查看最近的n次提交
git log --graph
![](https://i-blog.csdnimg.cn/blog_migrate/82e2f5cc48432794a96f8cff5f651b1e.png)
git reflog
当你执行一些更改到分支中,例如合并分支、rebase、reset、stash等操作时,都会影响到 HEAD 的位置,git reflog 可以记录这些变更,你可以使用 `git reflog` 命令来查看这些变更的历史记录。
使用 `git reflog` 命令可以在本地仓库中查看已经被删除的分支或提交。如果你的 Git 仓库被操作过程中意外删除了某个分支或提交,可以使用 `git reflog` 命令查找被删除的提交前的引用,然后进行恢复。
需要注意的是,`git reflog` 命令不会保存历史记录很长的时间,因此如果需要保存历史记录,请及时备份。
git reflog---恢复到指定的提交节点
git checkout HEAD@{n}
头指针在xxxxxx分离
git reflog查看的日志是操作之前的,还是操作完成之后的结点数据
是操作完成之后的。
git worktree
git worktree add 目录
git增加子模块
什么是子模块
怎么制作子模块
smartgit:
git:
git submodule add url (希望存放的文件路径)
如果之前添加过这个子模块或者子模块以目录的形式添加,再次添加时,报错怎么办
already exits in the index
解决办法:
1,删除之前的子目录或者子模块;
2,重新提交项目,让项目去除旧子模块的index;
3,重新git submodel add url就行。
添加子模块之后的HEAD分离
1,合并分离
在做修改之前,一定要先为HEAD指向的提交创建分支,合并再修改文件。
产生HEAD游离的原因
在Git中,HEAD游离是指HEAD指向了一个分离的状态,也就是HEAD指向的不是一个branch名称,而是某个具体的commit或tag。这往往发生在以下情况下:
1. 检查out具体的commit或tag
通过在本地仓库上使用`git checkout`命令,可以将HEAD指向某个具体的commit或tag,以用于查看代码库的某个历史版本。当HEAD指向的是一个具体的commit或tag时,就会出现HEAD游离状态。
2. 分支被删除
当HEAD所在的分支被删除时,HEAD将会指向commit或tag,这时就会出现HEAD游离状态。
3. 合并冲突
当在合并分支时,出现了冲突,但尚未解决冲突时,HEAD将指向合并的commit。如果在解决冲突前离开了该分支,就会导致HEAD指向一个具体的commit而不是分支,进而引起HEAD游离。
因为HEAD游离意味着你当前的代码不位于任何分支上,所以这对于后续commit和代码更新会带来一些问题。推荐在HEAD游离时,恢复所在的分支或者继续commit和push新的变更,以确保代码库的健康和稳定。
添加子模块产生HEAD游离的原因
添加子模块后,子模块中没有分支跟踪改动。
主项目的更改提交和子模块的更改提交
如果我们在主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到麻烦, 因为他
们无法得到依赖的子模块改动。那些改动只存在于我们本地的拷贝中。
为了确保这不会发生,你可以让 Git 在推送到主项目前检查所有子模块是否已推送。 git push 命令接受可以设
置为 “check” 或 “on-demand” 的 --recurse-submodules 参数。 如果任何提交的子模块改动没有推送
那么 “check” 选项会直接使 push 操作失败。
2,推送
最简单的选项是进入每一个子模块中然后手
动推送到远程仓库,确保它们能被外部访问到,之后再次尝试这次推送。 如果你想要对所有推送都执行检查,
那么可以通过设置 git config push.recurseSubmodules check 让它成为默认行为。
推送的原理
子模块是单独,独立的模块,需要单独推送,先推送所有的子模块,再推送项目;
子模块的删除
.gitmodules文件直接删除
git show
显示 Git 仓库中最新提交的时间戳
git show -s --format=%ci 的作用是显示 Git 仓库中最新提交的时间戳。
具体作用如下:
- git show:用于显示某个 Git 对象的信息。
- -s:指定 git show 命令只显示提交信息中的摘要行,而不是完整的提交信息。
- --format=%ci:用于控制 git show 命令所输出的提交信息的格式,其中 %ci 是格式控制符,用于输出提交的时间戳。
因此,执行 git show -s --format=%ci 命令,将会输出 Git 仓库最新提交的时间戳信息。时间戳采用 ISO 8601 标准格式,例如:2019-09-09 15:11:34 +0800。该命令常用于查看某个 Git 仓库最近更新的时间,或者在编写 Git 命令脚本时作为变量参数使用。
获取指定commit_id的时间戳
git show -s --format=%ci commit_id
git底层
git的实现语言
c语言
git add 生成文件快照
暂存操作会对每一个文件计算校验和,然后把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 类型的对象存储这些快照),并将校验和加入暂存区域。
每一个文件对应一个blob快照;
blob对象
blob是不是C的结构体
Blob 对象本身不是 C 语言的结构体。
git commit创建tree对象和提交对象
提交对象中的数据
1,包含零个,一个或者多个指向父提交对象的指针;
首次提交是没有直接祖先的,普通提交有一个祖先,由两个或多个分支合并产生的提交则有多个祖先。
2,包含提交信息,比如提交的作者等;
3,指向tree对象的指针。
commit对
tree对象
分支
本质上就是一个指向提交对象的指针;
这个指针的值可变。
创建分支
就是创建指针,这个指针指向当前提交对象。
HEAD指针
永远指向当前工作的指针(分支)
gerrit
git review
拉取change的代码
git review -d(download) chang号;
非分支,正变基
git review提交代码之后产生冲突----提示:非分支,正变基+分支名
原因:提交代码时, 产生冲突;
解决办法:
打开文件---修改冲突---保存--git add -u-----git rebase --continue;
还有冲突---重复以上步骤;
rebase完成之后---git review