对命令取别名
---------取别名文件在C:/Users/Administrator/.gitconfig中可以看到。
$git config --blobal alias.ch checkout //以后用ch就相当于用checkout了
设置vim编辑出现行号
:数字-----可定位到行
本地账号的设置
git工具的git bash here窗口可当linux端口操作,可用各程liunx命令,常用的命令
touch test.txt //创建文件
mkdir test //创建文件夹
pwd //查看当前目录
cd .. //返回到上一个文件夹
cd test //进入test文件夹
ll /ls //显示当前文夹所有文件
vim test.txt //编辑文件,ESC退出当前模式,:wq保存退出,:q退出
rm -rf 文件夹/文件名 //删除文件
出现的问题
-
kex_exchange_identification: Connection closed by remote host Connection closed by 20.205.243.166 port 22
具有可能是我的vpn启动了,退出可以正常,还有可以往下看设置代理,也可处理。
github.com设置代理,提高访问速度
GitHub 是经常的打不开,有时候克隆一个库很久都不下载不下来,很多时候都是超时无法下载,这种情况下我们只有挂代理提高访问速度。
首先你得一个可用的梯子(代理)Elephant
如果 socks5(SSR),你需要知道你本地的 socks5 代理 ip 地址和端口,默认打开的话就是 127.0.0.1 端口 6986,然后使用此命令设置代理
git 有几种传输协议,在Github上主要用到的是Https和SSH协议。所以我们要做的是对git 命令的https 以及ssh流量做代理。
Git代理有两种设置方式,分别是全局代理和只对Github代理,建议只对github 代理。
代理协议也有两种,分别是使用http代理和使用socks5代理,建议使用socks5代理。
注意下面代码的端口号需要根据你自己的代理端口设定,比如我的代理socks端口是6987.
全局设置(不推荐)
#使用http代理
git config --global http.proxy http://127.0.0.1:58591
git config --global https.proxy https://127.0.0.1:58591
#使用socks5代理
git config --global http.proxy socks5://127.0.0.1:51837
git config --global https.proxy socks5://127.0.0.1:51837
只设置 Github 的代理
git config --global http.https://github.com.proxy socks5://127.0.0.1:6986
git config --global https.https://github.com.proxy socks5://127.0.0.1:6986
取消代理
git config --global --unset http.proxy
git config --global --unset https.proxy
https连接的github.com 一个token.
//用户名 xiongshaowen
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
设置ssh代理(终极解决方案)
https代理存在一个局限,那就是没有办法做身份验证,每次拉取私库或者推送代码时,都需要输入github的账号和密码,非常痛苦。
设置ssh代理前,请确保你已经设置ssh key。可以参考[在 github 上添加 SSH key完成设置更进一步是设置ssh代理。只需要配置一个config就可以了。
# Linux、MacOS
vi ~/.ssh/config
# Windows
到C:\Users\your_user_name\.ssh目录下,新建一个config文件(无后缀名)
将下面内容加到config文件中即可
对于windows用户,代理会用到connect.exe,你如果安装了Git都会自带connect.exe,如我的路径C:\APP\Git\mingw64\bin\connect
#Windows用户,注意替换你的端口号和connect.exe的路径
ProxyCommand "C:\Program Files\Git\mingw64\bin\connect" -S 127.0.0.1:6986 -a none %h %p
#MacOS用户用下方这条命令,注意替换你的端口号
#ProxyCommand nc -v -x 127.0.0.1:6986 %h %p
Host github.com
User git
Port 22
Hostname github.com
# 注意修改路径为你的路径
IdentityFile "C:\Users\Administrator\.ssh\id_rsa"
TCPKeepAlive yes
Host ssh.github.com
User git
Port 443
Hostname ssh.github.com
# 注意修改路径为你的路径
IdentityFile "C:\Users\Administrator\.ssh\id_rsa"
TCPKeepAlive yes
保存后文件后测试方法如下,返回successful之类的就成功了。
测试是否设置成功
ssh -T git@github.com
之后都推荐走ssh拉取代码,再github 上选择clone地址时,选择ssh地址,入下图。这样git push 与 git clone 都可以直接走代理了,并且不需要输入密码。
很多朋友配置代理之后,可以正常访问github 网页了,但是发现在本地克隆github仓库(git clone xxx)时还是报网络错误。那是因为git clone 没有走你的代理,所以需要设置git走你的代理才行。
设置代理之前
如果在终端terminal命令行下载软件包速度不快,并不是代理不行,而是在终端terminal也需要进行相应的配置代理,同样的在命令行中git clone 某某工程时,即使终端设置了代理,GitHub也要再配置一遍代理,接下来看操作,命令行敲起来。
[user]
name = your_name
email = your_email
[http]
proxy = socks5://127.0.0.1:1080
[https]
proxy = socks5://127.0.0.1:1080
远程库修改删除操作
-
首先本地建一个文件mygitremote,git init把该文件夹纳入版本库管理,建六个文件如下图。
- 与远程库建立关联,并把所有文件放到暂存区
git remote add oirgin https://github.com/xiongshaowen/mygitremote.git
git add .
-
修改
一。提交,修改,撤回修改
-----如果某个文件,已提交,并且对其进行修改,可以放弃修改,还原到提交(刚刚提交的)状态。
git add . //把所有文件都放进暂存区staged
git commit -m "提交所有文件到对象区"
vi hello.txt //修改hello.txt ,加内容:如world hello,这时文件又回到工作区
git checkout -- hello.txt //撤回修改
cat hello.txt //查看一下文件内容,可以看到没了world hello
-----------------------------------------------提交后查询当前情形-------------------------------------
Administrator@10_0_12_3 MINGW64 ~/Desktop/githubtest/mygitremote (master)
$ git status
On branch master
nothing to commit, working tree clean
---------------------------------修改hello.txt没有add的情形--------------------------------------------------
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.txt
-----------------------------------------撤回修改查看hello.txt--------------------------------------
$ cat hello.txt
---------新建一个文件world.txt,马上放到暂存区,git add world.txt,可以reset或cache撤回到工作区的命令如下,如同上面修改文件没有add的一样。
touch world.txt
git add world.txt
git reset head world.txt
二,删除已提交的文件
1---git rm命令删除
----use "git restore --staged <file>..." to unstage表示删除的文件可用git restore --staged xxx回到工作区,即表明它现在在暂存区stage.现在只有两个操作了,要么再提交(彻底删除),要么就放在暂存(看不见)
git rm 文件名
例:删除b.txt,后查看状态,显示b.txt在暂存区了
$ git rm b.txt
rm 'b.txt'
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: b.txt
----删除后悔操作,前提是没有提交
------可以先用git status查看当前库的中文件状态,看没没有‘changes to be committed:下面的deleted:xxxx有什么文件“,如有,则可后悔。
$git reset HEAD hello.txt //恢复到工作
$git checkout -- hello.txt //回到提交的状态,后悔了。
2---rm 操作系统删除
-----该删除会把文件放到工作区了,想要彻底删除,则要提交到暂存,再commit.
三,重命名 git mv xxx xxx和操作系统mv xxx xxx
1---git mv
-----本质是,先移动文件,复制了一份,再删除旧文件,涉及到了两个文件,从这可以看出,可以恢复旧文件。
例:我重命hellowrld.txt 为hello.txt
$ git mv hellowrld.txt hello.text
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: hellowrld.txt -> hello.text
恢复旧文件(后悔了)hellowrld.txt
$git reset HEAD hellowrld.txt //回到工作区,下面也提示,可以add 了
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.text
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: hellowrld.txt
$git checkout -- hellowrld.txt //回到提交的状态,新文件还在暂存区,可以提交它
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.text
--------------------------------------------------------------------------------
$ ls
a.txt abc.txt hello.text hello.txt hellowrld.txt wrold.txt
2---操作系统 mv xxx xxx
-------操作后,两文件都在工作区了,可以先放到暂存区,再提交,但旧文件删除了,不能恢复了。
$ mv hello.text hellonew.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: hello.text
Untracked files:
(use "git add <file>..." to include in what will be committed)
hellonew.txt
no changes added to commit (use "git add" and/or "git commit -a")
四,重命名,提交的注释信息(-m后面的信息)
------思路:先查看提交信息
$git log -2 //查看最近两次的提交
Administrator@10_0_12_3 MINGW64 ~/Desktop/githubtest/mygitremote (master)
$ git log -2
commit 826d1bbf637190b07f01f675848c4c1dd84400b1 (HEAD -> master)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 15:25:28 2023 +0800
fsdaf
commit e3fb20214b2f10bc88344c5fc4d2009ab79f50b0
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 15:18:57 2023 +0800
提交新文件
------再后:修改之(下面是修改最近的一次)
$git commit --amend -m '修改’
[master 0c1eb08] modify
Date: Sat Apr 8 15:25:28 2023 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
rename hello.text => hellonew.txt (100%)
$ git log -2 //查看最近的两次提交信息
commit 0c1eb083fe77cf86b3e57ba97399c2dfe3583924 (HEAD -> master)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 15:25:28 2023 +0800
修改
commit e3fb20214b2f10bc88344c5fc4d2009ab79f50b0
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 15:18:57 2023 +0800
提交新文件
五,忽略
-----发布项目时,我们提交只是提交代码如java文件,而一些配置文件是不用提交的,因为如上图中a.properties配置文件里的路径可是不一样的。我放在resources中,别人可能放在其它地方。所有我们上传时要忽略它,不上传。
例:模拟忽略文件a.properties
首先:,建两个文件a.properties,.gitignore,用git status,可以看到两个没有add的文件
$touch a.properties
$touch .gitignore //忽略之配置文件
$git status //可以看到两个文件
$ git status //可以看到两个文件处于add之前状态
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
a.properties
nothing added to commit but untracked files present (use "git add" to track)
***然后:我们编辑.gitignore文件,加上a.properties,:wq保存退出,再git status,不认识a.properties文件了(这时是没有add的时候)
$vim .gitignore
------------------------------------------------------------------------------------
a.properties //或写 *.properties通配符*表示任意长度的任意字符串
------------------------------------其它常用的正则表达式
*.properties
!b.properties //不忽略b.properties,!常与*一起用。
dir/: //忽略dir目录中的所有文件
dir/*.txt //饭略dir下的所有txt
dir/*/*.txt
dir/**/*.txt //忽略任意级别目录下的所有txt
空目录 //默认忽略
-------------------------------------------------git status-------------------
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
分支管理
-----分支在新建的时刻,它里的内容与创建分支的分支一样,如master,后面就各自独立操作。如以master为根据创建分支,此时新的分支内容与master一样,后面就是各不相干。
-
新建分支
-----新建的那时刻,xxxx分支也具有abc...的文件。后来互不相干。
例:以master创建new_branch分支,并切换到new_branch,并马上查看有什么文件
$git branch //查看分支情况,带*号的为当前分支
$git branch new_branch //只创建分支
$git checkout new_branch //只切换分支
$ git checkout -b new_branch //创建并切换到分支
Switched to a new branch 'new_branch'
Administrator@10_0_12_3 MINGW64 ~/Desktop/githubtest/mygitremote (new_branch)
$ ls //在new_branch中查看有什么文件,可以看到相当于复制一份master的内容
a.properties abc.txt hellonew.txt wrold.txt
a.txt hello.txt hellowrld.txt
注意:创建分支,并切换后,如果创建它的地方没有内容,(master没有内容),再切换回master不成功.
在HEAD指回master分支后,需要将工作目录恢复到master分支所指向的内容。但是由于你从开始一直在develop分支上进行操作,master分支对应的工作目录相当于还什么都没有,这样就出现匹配不到任何文件。
-------如何解决
你只需要在初始化一个仓库后,先在master分支上进行一些commit操作,比如增加一个README.md文件,这样就真正创建了一个master分支。
- 删除或增加分支内容,再切换分支,看看情况
假设当前分为new_branch,创建b.properties,c.properties,再add . 再commit提交
$touch b.properties
$touch c.properties
$git add .
$git commit -m "bc.properties"
- 分支删除 git branch -d new_branch
注意:删除分支,以下情况不可删除
一,不可自已删除自已
二,没有合并内容的分支建议不删除,为了保护数据,可以强删除用大写-D。
-----如上,new_branch增加了两个文件,此时在master下删除new_branch会出错
$ git branch -d new_branch
error: The branch 'new_branch' is not fully merged.
If you are sure you want to delete it, run 'git branch -D new_branch'.
$git merge new_branch //合并分支,后可以再小写-d删除,合并后的master内容是两个分支合并
git branch -v查看每个分支的提交情况
删除分细节:
1---如果在分支A中建一个文件(删除,修改),没有(add,commit),则切换到主分区(如master)中,可以看到A分支创建的文件操作。
2---如果如果在分支A中建一个文件,有(add,commit),则切换到主分区(如master)中,不可以看到A分支创建的文件操作。
3---如果在分支A中建一个文件,没有(add,commit),则切换到主分区(如master)中,可以在主分区中小写-d删除A分支
分支的合并与冲突
- 分支没有冲突的合并。
----分支:是一个commit链接,一条长链,通过sha1值链起来,下一个分支可以通过sha1找上父分支。
---HEAD是一个指针,一直指向commit,所以通过它能回退提交的版本。
例:有一个分支链条,刚开始git init自创建一个主分区,HEAD指向它和它的提交版本,这可以从.git文件夹的HEAD文件中看到ref: refs/heads/master
,同时创建一个a.txt文件,再add . ,commit -m "init".
$mkdir mygit
$cd mygit
$git init
$cat .git/HEAD
ref: refs/heads/master
$git add .
$git commit -m "init"
然后:建一个分dev,且切换到dev分支,在dev中创建一个文件b.txt,并提交commit -m "dev1",再git log查看HEADR指向,表明HEAD是跟着commit走的
$ git checkout -b dev
Switched to a new branch 'dev'
$ cat .git/HEAD
ref: refs/heads/dev
$ git log //在dev分支中可以看到此时HEADR指向dev,dev再指向master的sha1值(239171.……)
commit 2391712725dfaf3381ad45f5ff032d2b0bb56e05 (HEAD -> dev, master)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 22:00:40 2023 +0800
init
$vim b.txt //输入b
$git add .
$git commit -m "dev1"
$git log
commit 5f7d2cb82887dea618eed85d68dfc788e112b412 (HEAD -> dev)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 22:10:22 2023 +0800
dev1
commit 2391712725dfaf3381ad45f5ff032d2b0bb56e05 (master)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 22:00:40 2023 +0800
init
$ git checkout master // 切换到master分支,查看得到HEAD
Switched to branch 'master'
Administrator@10_0_12_3 MINGW64 ~/Desktop/mygit (master)
$ git log
commit 2391712725dfaf3381ad45f5ff032d2b0bb56e05 (HEAD -> master)
Author: xiongshaowen <65179334@qq.com>
Date: Sat Apr 8 22:00:40 2023 +0800
init
dev分支再提交一次
$vim a.txt //修改主分区创建的文件,加:ab
$git add .
$git commit -m "dev2"
[dev 707e18f] dev2
现在master落后,两步了,又不冲突,为了追上dev,可以合并dev两次提交的版本,这叫快进Fast forward
$git checkout master //切换到主分区
$git merge dev //合并分支dev
Git在merge时,默认使用fast forward,也可设置不用,git merge –no-ff 分支
1, 两个分支合并禁用fast forward,不会归于一点commit,主动发起合并的分支,会前进一步)
2, 分支信息完整(不会丢失分支信息),可用git log –graph查看commit信息,就知道了。
----现在我们,又到dev分支进行两次提交 dev3,dev4.又回到master合并dev3,dev4,这次带参数合并,禁用fast forward
$git checkout dev
$vi a.txt //加点内容
$git add .
$git commit –m “dev3”
$vi b.txt
$git add .
$git commit –m “dev4”
$git checkout master
$git merge --no-ff dev
从下图可以看出,master发起的两合并,是不同的,第一次归于一点了(在dev2链上,而第二次发起合并,前进了一步,绿线也指示出了分支信息保存了下来)
- 合并时冲突,要处理冲突
首先:建立冲突场景,分别在上次合并后的各分支中都修改a.txt的第二行内容(两个分支共享一个内容),都各自add . commit .
//假设当前在dev分f支
$vim a.txt //第二加 dev
$git add .
$git commit -m "dev"
//切换到 master
$git checkout master
$vim a.txt //第二加 master
$git add .
$git commit -m "master"
然后:到任 一分支中发起合并,我选master中发起,发起后,会产生冲突,如下内容。
//假设当前在master分支,发起合并
$ git merge dev
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
再然后:处理冲突,即我们可以在一分支中(发起合并的)用vim a.txt 修改即可,删除>>>>>等字样。
$vim a.txt
$git add .
$git com
处理完冲突后,再add . commit ,再合并就没问题了,合了后:master会把dev修改的a.txt内容同步进它的a.txt文件,相当于master两次修改提交。还有,如果此时我们再回到dev分支中,来合并master不会出错了,因为master又前进了一步,事实上,只要两个分支处在同一时刻中(每一次merge后,处在同一个时刻中,刚刚创建分支时,两分支也处同一时刻),快进合并就不会产生冲突,如果同一时刻都有修改同一内容,再提交(次数不限,合并都是以最近一次提交为依据合并),再任谁合并谁都会产生冲突
分支的内容版本管理,与分支重命名等
1.版本回退,即版本穿梭
-----我们每执行一次commit,就产生一个版本。执行git log可以看到当前所有的提交记录,也就是每个版本的信息。每个版本都有一个commit id,版本回退的时候,只需要执行git reset --hard commit_id(commit_id不需要输完,输入前6位即可),就可以回退到对应的版本中。
------github有一个HEAD指针,指向当前版本。如下图,最上面的是最新的版本,执行版本回退之后,github只是将HEAD指针指向了历史版本而已。
------如果我们回退了版本之后,后悔了,又想恢复到较新的版本,怎么办呢?由于这个时候执行git log是看不到较新版本的记录的,需要执行git reflog才行。这个时候我们就得到了所有版本的commit_id,再执行git reset --hard commit_id,就可以吃上后悔药,恢复到较新版本了。
git log -number //会显示最近三提交版信息
git reflog //会显示所有版本id,包括已回退到版本前后版本id,因回版本修改了,后,git log已经不显示回退之前的版本了。
git reset --hard HEAD //上一个版本
git reset --hard HEAD^ //回退到下一个版本,加多个^可以退回到多个下一版
git reset --hard HEAD~100 //则是往前倒数第100个版本
git reset --hard commit_id //回到版本号(sha1值的前6位即可)的位置,一般先要用git reflog查询版本号。
checkout做版本穿梭,它穿棱后,成为游离状态detached,这时若修改了内容一定要add . commit,不然的话穿棱不回去,游离状态是创建分支的最好时机***
例:对分支dev做了四次修改,提交,有多个版本。然后checkout穿棱到版本三,版本三游离出去了,独立的。
$git checkout 版本三sha1值 //游离了,通过git log 查询到commit_jd(sha1)
$vi a.txt
$git add .
$git commit -m "游离时修改了内容,必须提交"
$git checkout mybranch 2735603 //创建分支,并命名,带上sha1值,该值在上面的穿棱时有给出建议
$git checkout master //回到现在,
2.管理修改(vi 内容)
不管是在暂存区,还是对象,只要一vi修改,就会回到工作区,但在暂存区时,再修改,它只是复制一份到工作区中,暂存区的不会丢失,只有再add .就会覆盖,可再提交,对象区的一修改不移到工作区了。
举例:建一个版本库mygittest ,git init ----vi a.txt 输入aaa,---->git add . ----git commit -m 'init'------>vi a.txt 输入内容bbb,这时,对象区中没有内容了。我又把a.txt 放到暂存区,git add .再又修改vi a.txt输入ccc,这时就是如下图所示的情情了。有两份a.txt了,一份在暂存区,可直接提交,一份在工作区(unstage)可以add 了。但查询内容是工作区的cat a.txt
注意!可用:git reset HEAD a.txt,可以把a.txt推回到工作区,相当于移动
$ cat a.txt
aaaa
bbb
ccc
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: a.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
如上情况。1.放弃工作区修改
$git checkout a.txt
$git commit -m "放弃工作区的ccc,再提交是暂存区的那份,没有ccc内容"
******如上情况。2.放弃对象区修改***
----这个时候,内容只是存在于对象区中,这个时候直接执行git checkout -- a.txt即可(即把版本库---对象区的a.txt签出到工作区)。注意"--"不能少,不然就是切换分支了,或是把工作区的丢掉。再执行git checkout -- a.txt将修改从工作区中删除
$vi a.txt //输入xxxx
$git checkout -- a.txt //回车后,仍是对象区中上次提交的样子,等于是没修改
3.删除文件,如何恢复
----假设我们分支里有一个test.txt文件(即已经commit到分支),这个时候我们在工作区中把test.txt删除了,该如何恢复呢?由于版本库中还有test.txt,我们只要把它签出即可:git checkout -- test.txt。当然还有另一种情况,就是我们确实是要删掉test.txt的,那么我们需要先执行git rm test.txt,再执行git commit -m "xxx"即可。这和新增修改是一样的。
4.分支管理
方法1,创建分支的同时,切换到新建分支:
git checkout -b dev # dev是新建分支名
方法2:,先新建分支,再切换:
git branch dev
git checkout dev
git branch //查看当前分支
5.合并分支
想把dev合并到master分支,那么需要先切换到master,然后再merge:
git checkout master
git merge dev
上面的方式是Fast-forward模式,即“快进模式”,直接把master指向当前的提交。这种方式速度快,但是有一个缺点,就是当我们把dev分支删除后,dev分支的信息就丢失了。如果希望保留dev分支信息,可以用--no-ff方式:
git checkout master
git merge --no-ff -m "merge with no-ff" dev
这样相当于新建了一个commit(看到-m这个参数了吗),通过下面的命令,我们可以看到这个commit的信息:下面的显示版本信息比git log 显示的信息简单明了,一行显示一个版本信息。
git log --graph --pretty=oneline --abbrev-commit
这个时候就可以把dev分支删除了:
git branch -d dev
6.分支重命名,master都可重命名,当然了不这样做
$git branch -m master master2
7.stash保存现场
一,建议(规范):在功能没有开发完毕之前,不要commit
二,规定:在没有开发完毕之前,没有commit之前,不能切换checkout 分支(不在同一个commit阶段---merge合并后了的时候,是同一个阶段),这时可以用stash保存现场,再切换。
例:我正在dev分支中开发,没有完毕, 但经理跟我说master分支有任务要做,很急,我就马上切换到master去,又不可提交,因为没做完,所以在此时的dev中保存现现场
$git stash [现场名] //[]表可选
$git checkout master //做了活,又回到dev中,此时刚刚没提交的东西看不见,这时我们要恢复现场
$git checkout dev
$git stash list //查看现场列表,如果只有一个场,直接下条命令即可恢复
$git stash pop //还原现场,并删除现场
$git stash apply //还原现场,并保存现场 ,若要删除则用 git drop stash@{数字}
$git drop stash@{0} //删除指定的现场
-----------------------------------------------------------多个现场时---------------------------------------------
$git stash save my1
$git checkout master
$git checkout dev
$git stash list
$git stash apply stash@{1} //还原再拨,不删除现场
***保存现场冲突----如两次退出前保存现地时,修改了同一文件同一行,处理:vi ***
8.tag标签,给版本写标签
--------常用于commit后,
tag标签 :适用于整个项目,和具体的分支没关系
git tag xxx
git tag -a xxx -m "xxxx"
查看标签git tag
删除标签 git tag -d 标签名
$git tag -d v1.0 //删除标签
例:现在库中有文件a.txt,两个分支dev master.我在dev中修改了两次文件,提交了两次,也分别打了两个标签。下面看操作。
$git checkout dev
$vi a.txt //输入tag
$git add .
$git commit -m "first tag"
$git tag v1.0 //创建标签1,名为v1.0
$vi a.txt //输入tag2
$git add .
$git commit -m "second tag"
$git tag v2.0 //创建标签2,名为v2.0
$git tag -a v2.0 -m "release Tag" //创建标签的另一种形式,有注释信息,表明发布版
$git tag //查询所有标签
v1.0
v2.0
$git tag -1 "v*" //模糊查询标签,这是查一个,名为v开头的所有标签
v1.0
切换到master,再查看标签,可以看所有标签,表明标签适用于整个库
9.blame:责任
$git blame a.txt //查看a.txt的所有提交commit sha1值,以及每一行的作者,可以用于追责
^967737a (xiongshaowen 2023-04-10 09:24:24 +0800 1) aaaa
5ba155c2 (xiongshaowen 2023-04-10 09:43:29 +0800 2) bbb
10.diff差异性
-----diff是linux命令,本身不是git的。可以在linux终端式的窗口中用。
例如:下面库中两个文件a.txt,b.txt.,再用diff a.txt b.txt后
$diff -u a.txt b.txt
--- a.txt 2023-04-10 12:58:45.951439500 +0800 //---表示源文件,+++表示对比的文件,其它是修改日期时间
+++ b.txt 2023-04-10 12:58:45.951439500 +0800
@@ -1,6 +1,7 @@ //-表源,+表对比的,从第一行开始比较
aaaa
bbb
-cc //内容上的加减号表,加上内容到源文件,从源文件减去内容,两个文件内容一样了。
+ccc
dd
hello dev
-▒▒▒▒▒▒
+hello dev2
+hello dev3
\ No newline at end of file
-----git diff :暂存区 和工作区的差异,工作区 和 某个对象区的差异,不是不同文件的差距。
例:暂存区,工作区的差距(注:左源,右目标)
vi a.txt //输入 first line.....
git add .
git commit -m "init"
vi a.txt //输入第二行 sencod line...,此时把对象区的a.txt复制到工作区了
git add . //此时此刻,a.txt回到暂存区了
vi a.txt //输入第三行 three line ....,此时,把a.txt复制一份到工作区了,不是移动
现在比较暂存区和工作区的差异
$git diff
warning: in the working copy of 'a.txt', LF will be replaced by CRLF the next time Git touches it
diff --git a/a.txt b/a.txt
index 05e3fe0..1e0185d 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,3 @@
first line...
second line... //表明两区的前两行是一样的,因为前面没有符号(+,-)
+three line... //+表明暂存区只要加three line...后,都一样了。
现在比较对象区和工作区的差异
vi a.txt //输入 111111111
$git add .
$git commit -m "init"
$vi a.txt //输入 2222222
$git diff sha1值(“init‘的)
现在比较 最新的对象区和工作区的差异(HEAD),一定要注意是:左源,右目
$git add .
$git commit -m "init2" //把上次工区的222222提交到对象区
$vi a.txt //输入3333333,再马上比较之,
$ git diff HEAD
warning: in the working copy of 'a.txt', LF will be replaced by CRLF the next time Git touches it
diff --git a/a.txt b/a.txt
index 1640270..ce427e6 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,3 @@
11111111111
22222222222
+33333333333
git diff --cached commit的sha1值 : 对象区和 暂存区的差异
git diff --cached HEAD : 最新对象区和 暂存区的差异
本地到远程的操作(推送,拉取)
push:本地->github
pull:github->本地 , pull = fetch + merge
rm -rf * :当前目录中的文件、子文件目录全部删除(不会删除隐藏文件、不过回收站)
.....rm ..... -rf / ......:不要执行,删除整个计算机中的全部文件
github的仓库中,默认的说明文档README.md
推送
- 建立与远程的关联。
首先:注册一个远程账号(65179334@qq.com ,xiongshaowen,cexoit1983)
然后:建一个远程仓库git2023(作为此测试用)
再然后:本地建同名的仓库git2023,再配本地账号,公钥,等,再建一些文件,如a.txt,b.txt
$git init //把该文件夹纳入git管理库
$vim a.txt //建a.txt文件,输入一些内容
$ git config --global user.name "xiongshaowen"
$ git config --global user.email "65179334@qq.com"
$ ssh-keygen -t rsa -C "65179334@qq.com"
$ssh-keygen //光这个命令也可生成公钥用,
//在c:/user/Administrator/.ssh中产生公钥文件id_rsa.pub,把内复制到远程官网的new sshkey中,
//公钥一般用于ssh协议连接,这样我们就可用它了,可免密码推送拉取,不过地址是git开头的。
//生成公钥也可
$ssh -T git@github.com //测试可以连通远程官网不,如果成功会出现下面的字符串
Hi xiongshaowen! You've successfully authenticated, but GitHub does not provide shell access.
再然后:把文件add .,commit ,再建立关联,再后push推送 ,除第一次推送外,后续更新推送只要git push即可,不用带后面的参数。
$git add .
$git commit -m "inita.txt"
$git remote add origin https://github.com/xiongshaowen/git2023.git //origin是远程库的别名
$git remote add origin git@github.com:xiongshaowen/git2023.git //ssh协议关联远程仓库,前提是把公钥放进远程账户或库中。
$git push -u origin master
$git push //后续修改推送,不用写上-u origin master了。
上面push后,会弹出一个网页,让我们输入:账号,密码(远程的),再又弹出对话框,让我们输入账号,token.
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 一个token
ssh协议,不用输入token,但要生成私钥id_rsa,公钥id_rsa.pub,私钥留本地,公钥复制放到远程仓库或系统中,这样可免密钥推送拉取。本人把C:/Users/Administrator/.ssh与.gitconfig两个文件打包,放进网盘里,用的时候下载解压以原来同样的方式放进相同的目录里,这样在网吧咖啡图书馆,也可直接用,公钥事先搞到远程账里了。
- 分支推送布局
dev->test(merge dev)-->master(merge test)
dev:开发分支,频繁改变
test:基本开发完毕后,交给测试实施人员的分支
master:生产阶段——,很少变化
bugfix:临时修复的分支
origin/master表示远程分支,在我们推送拉取时,我们是与它来感知远程信息的,它处于游离状态,一但修改就要提交
$git remote show #查询远程服务器
origin //当前只有它了
$git remote show origin //显示远程服务器具体信息
* remote origin
Fetch URL: git@github.com:xiongshaowen/git2023.git
Push URL: git@github.com:xiongshaowen/git2023.git
HEAD branch: master
$git status
Your branch is up to date with 'origin/master'. //origin/master表示远程分支,up to date与。。。一样最新的
克隆与拉取
如果本地没有搞仓库,则可以直接从远程克隆来到本地,不过克隆过来的是以远程仓库名命名的文件夹,并放在本地。
本例:以ssh协议从远程仓库中克隆库到本地,事先已配好了公钥,私钥(放本地),第一次克隆过来,不用git init,克隆后,再进入克隆过来的文件夹中,直接用git等操作。
//$git clone 远程地址 【库别名】
$ git clone git@github.com:xiongshaowen/git2023.git
Cloning into 'git2023'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$ cd git2023 //进入本地版本仓库,已经被初始化了
Administrator@JTCH-096 MINGW64 ~/Desktop/githubtest/git2023 (master)
本地与远程冲突处理
push/pull:推送,改变指针
-----当在云主机上,提交修改,再push后,head指钟指向origin/master(远程库感知库),而origin/master处于游离状态,即可让所有与远程库关联的用户感知,此时别处用户没有pull的情况下,查询origin(git remote show origin)即可看到它提醒该用户要pull的了,你版本过期了(out of date).
//在网吧的本地库查询origin/master
$git remote show origin
现在我更新网吧的本地库,git pull不用带参数啥的,因为克隆时已经自动建立远程关联了。
Fast-forward :更新, 如果发现 更新的内容 比自己先一步(commit 的sh1值 在自己之前),则 会自动合并
$git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 228 bytes | 76.00 KiB/s, done.
From github.com:xiongshaowen/git2023
4a83ff0..dd70d71 master -> origin/master
Updating 4a83ff0..dd70d71
Fast-forward //注意,注意
a.txt | 1 +
1 file changed, 1 insertion(+)
制造冲突场景
现在本人,在云主机上,有一个版本库,本地账号:tenxinyun,在家或网吧有一个版本,本地账号:xiongshaowen,三个地方的库是同名的,并通过推送克隆等操作,内容都一样。
$git config user.name //查询本地账号名
xiongshaowen
$ls
a.txt //现在库中都有a.txt文件
冲突的产生:现在我在腾云主机上修改a.txt的第一行,再add . commit ,push。又在网吧主机上也修改a.txt第一行,再add . commit ,push会出错,产生冲突了。
处理冲突:
1.pull
2.fetch+merge
总: pull = fetch + merge
pull冲突处理
我们直接pull了以后,fetch百分之百分成功,但还会有冲突,这是merge出了错误 ,这时我们要去vi a.txt把文件修改好,再 add .告诉远程,再commit,再push。修改时可能会产生.swap文件,要删除之。
还没有完,此时腾云主机也要pull一下,才能让两地库达到最新的,即三方都处在一个commit 链点上(sha1值相同)
$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 286 bytes | 95.00 KiB/s, done.
From github.com:xiongshaowen/git2023
dd70d71..8d66d75 master -> origin/master
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt //冲实还有
Automatic merge failed; fix conflicts and then commit the result.
----------------------------------------------------修改:vi a.txt---------------------------------
<<<<<<< HEAD
home网吧冲突产生
=======
home腾云产生冲突
>>>>>>> 8d66d75df2431524360536be19fbcd003becfad7
tenxinyun
---------------------------------------------改好后--------------------------------------------
两个人商量好了,留下腾
home腾云产生冲突
tenxinyun
---------------------------------------------------add . commit push---------------------
$git add .
$git commit -m "网吧处理好了冲突"
$git push
$git remote show origin //再去查看一下远程情况,没有冲突(conflict)提示了
----------------------------------------------腾云再pull一次,达到三方同处一个commit链点上----------------------------------
$git pull
fetch+merge处理
在网吧本地库中,先fetch,拉取到本地,百分之百分更新(刚刚腾云主修改了a.txt第二行的内容)到origin/master分支上(游离状的分支),然后,我在网吧本地也修改a.txt第二行,然后也add . commit ,再git merge(合并origin/master,本地master) ,就会看到冲突了,这时,就要商量着修改vi a.txt。再提交,push.最后又到腾云主机去pull了,达到三方同一。
$git fetch
$vi a.txt //输入:
$git add .
$git commit -m "网吧第二次造冲突,fetch+merget处理"
$git merge //合并origin/master,本地master,提示有冲突
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
------------------------------------------------解决冲突之vi a.txt----------------------------
两个人商量好了,留下腾
home腾云产生冲突第二次制造冲突,用fetch+merge处理
tenxinyun
-----------------------------------------------再次add . commit ,merge----------------------
$git add .
$git commit -m ""网吧第二次冲突处理好了,vi a.txt"
$git merge //这次可以不用操作,直接push
Already up to date.
--------------------------------------------------push---------------------------------
$git push
----------------------------------------最后,到腾云主机pull------------------------------
$git pull //达到三方同一。
"
模拟远程冲突场景都可以在本地制造
1.设一个用户 --local xiongshaowen 65179334@qq.com,操作mygit1库。不用担心全局用户重名,因为--local优先级高于system, global.
$git init //先初始化mygit1为版本库,利用了全局用户名xiongshaowen,先前做的
$git config --local user.name 'xiongshaowen'
$git config --local user.email '65179334@qq.com'
//本地用户名会在该本库的.git文件中的config中找到
$git remote add origin git@github.com:xiongshaowen/git2023.git
$vi a.txt //如果远程仓库没有东西,等下的提交,push会出错,所以我们先建一个文件,再add .commit,push
$git add . //git add *也可将所有文件放进暂存区,但它不能全应到git语法,如忽略设置的东西
$git commit -m "xiongshaowen init"
$git push -u origin master //初次发布,要用到 -u origin master,后续只要git push即可
2.设另一个用户--local xuhuifeng 1067854873@qq.com本项目用户操作mygit2库
$git init
git config --local user.name 'xuhuifeng'
git config --local user.email '1067854873@qq.com'
$git remote add origin git@github.com:xiongshaowen/git2023.git
$git pull origin master //初次更新远程到本地,要用到origin master或其它分支名,后续只git pull即可
3.sshkey配置,只要一个就可以了,因为它是整个计算机的,但不同的计算机就要别配sshkey了。两个用户都可以用。
git 图形工具
gitk 、gui 、github desktop
gitk
$gitk
git gui
为了看到效果,刚建一个文件(b.txt),没有add. commit等。
另打开一个git bash here窗口,我们修改暂存区的文件后,再回到gui窗口,点‘Rescan',可在工作区看到修改了没有提交的文件。
放入暂存区,点'Stage Changed'
github desktop到desktop.github.com官司网下载
远程到本地分支管理
- 创建分支并关联
查看远程分支日志和查看地本与远程分支情况
$git log origin/master //或git log refs/remotes/origin/master
$git branch -av //查看本地和关联的远程分情况
* master a621745 xuhuifeng init //本地
remotes/origin/master a621745 xuhuifeng init //本地关联的远程分支,也叫追踪分支
本地到远程
一,如果本地有分支dev,远程没有dev,但关联了master分支
$git branch dev //创建本地一个分支dev
$vi a.txt //输入:localcontent
$git add .
$git commit -m "localcontent提交“
$git push //这里没有切换分支的话,仍推送到远程master分支中,
$git checkout dev //切换到本地的dev分支
$git add .
$git commit -m "dev提交”
$git push //直接推送,这样会出错,没有指定远程分支dev,远程没有也没关联
fatal: The current branch dev has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin dev
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
$git push -u origin dev //这样就推送到了远程自动产生的dev分支中,并关联了(dev<--->origin/dev)
//git push --set-upstream origin dev //这个与上条语句功能相同
//git push origin dev:dev2 //可以把本地分支dev推送到远程dev2上。
二,远程有dev分支,本地没有dev
1.git pull :远程-->追踪分支,还没有把dev放到本地来。
2.追踪分到本地:并切换到本地的dev中
1.git checkout -b dev origin/dev
2.git checkout -b dev --track origin/dev // -b dev可省略。但两分支不同名,就不能省,一般不这样做。
3.git pull origin dev:dev2 //不同分支名拉取
4.git fetch origin dev2:refs/remotes/origin/helloworld //将远程分支dev2拉取到本地并自动创建的本地分helloworld中。
- 删除
一,删除本地分支,当然了自已不能删除自已,再删除远程
格式:git branch -d/-D 本地分支名 删除本地分支
格式:git push origin src:dset 本地src为空,远程dset为真实分支名,删除了远程分支
git push origin --delete dset
$git branch -d dev2 //git branch -D dev2强制删除,但远程的dev2还在
$git push origin :dev2 //删除了远端dev2,git push origin --delete dev2也可删除远程dev2分支
二,先远程删除了分支,本地现在不需要,也要处理之
1.先查询我们不需要的追踪分支(它是感远程用的)
$git remote prune origin --dry-run
Pruning origin
URL: git@github.com:xiongshaowen/git2023.git
* [would prune] origin/dev2 //提示dev2可以不用了,远程没有了。
2.清理对应远程删除的分支
$git remote prune
- 版本标签tag
创建推送
-------------每一次提交(不管什么分支)都可打一个标签。一般用用标识版本性质,如发布版RELEASE,测试版。。。
git tag v1.0 //简单标签只存储当前commit节点的sha1值
git tag -a v2.0 -m "我是2.0版" //会产生新的提交即新的sh1值,肯定包侌当前刚刚提交的sha1值。
-------------推送标签
git push origin v1.0 //在那个分支上推都可看到
git push origin v1.0 v2.0 //同时推送多个标签
git push origin --tags //所有都推送
获取标签
$git pull //只拉取标签,不要用这个
$git fetch origin tag
$git fetch origin tag v1.0
删除远程标签
一,官网上直接删除
二,命令行删除
$git push origin 空格:v1.0
远程删除标签后,本地不能用pull感知,要手工删除,pull是前提,一定要执行
$git tag -d v1.0
裸库,子模块
- bare
-------没有工作区的仓库,只存在服务端,是由拉取推送操作,没有add 操作。
例:新建一个文件件夹mygit,
$git init --bare
- submodule
应用场景:在一个仓库中引用另一个仓库的代码
举例:
首先:本地建两个库A,B分别初始化git init,B本地账号xuhuifeng,1067854873@qq.com.远程也建两个公开库A,B.
git@github.com:xiongshaowen/A.git
git@github.com:xiongshaowen/B.git
$git init
vi a.txt //aaaa
$git add .
$git commit -m "ainit"
$git remote add origin git@github.com:xiongshaowen/A.git
$git push -u origin master
cd ..
cd B
$git init
$git config --local user.name xuhuifeng
$git config --local user.email 1067854873@qq.com
vi b.txt //bbbb
$git add .
$git commit -m "binit"
$git remote add origin git@github.com:xiongshaowen/B.git
$git push -u origint master
现在搞定本地与远程的关系,可以做子模块了,我们是A引用B
-----git submodule add ....
cd A
$git submodule add git@github.com:xiongshaowen/B.git
$git add .
$git commit -m "把B库加入了进来:"
$git push
----本地A库的样子
----远程端的A库的样子
然后:我修改B库的内容,add . commit push,再分别进入A库git pull,再进入A中的B:git pull,再又返回A:add . commit push.
//进入B库
$vi b.txt //输入:modify B reporistory
$git add .
$git commit -m "修改了B库"
$git push
//进入A库,更新B提交的新内容
$cd xxxx/A
$git pull
$cd B //当前A库的B库
$git pull
//返回A库根目录
cd ..
$git add .
$git commit -m "把B库的更新更新到远程A库的子库B中“”
$git push
最后:这样我们就得到了一个远程与本地库的引用达到一致了
一下子pull所有子模块
-----当子模块很多时,上面的pull方式很烦锁,可以这样搞
$git submodule foreach git pull
克隆项目怎么把子模块也一起克隆呢?这样做
$git clone ssh地址 --recursive
删除子模块
首先:删除暂存区,主要内容,因为对象区的内容不可删除,修改都是复制一份到工作区,所以先删除暂存区,再告诉对象区
然后:删除工作区,有一些配置文件上传时不会上传的,一直在工作区,如.gitmodules
最后:add . commit ,push
$git rm --cached B
$rm -rf .gitmodules
$git add .
$git commit -m "删除了子模块B"
$git push
substree类似submodule但双向的
- substree
与submodule功能相似,但它双向操作,一般建议使用submodule单向的。
例:paretn,subtree分别为远程和本地建仓库,本地直接初始化,不用克隆,再git remote add xxx建立关联,最后实现parent修改已引入的subtree项目,再实现真正的subtree感知更新,反之亦然,双向的。
一,建立关联与上面submodule方式一样,parent中有a.txt,subtree中有b.txt
//------parent中
$git init
$vi a.txt //输入:aaaa 或echo aaaa > a.txt ,建一个文件a.txt内容为aaaa
$git add .
$git add commit -m "parent init"
$git remote add origin git@github.com:xiongshaowen/parent.git //远程库别名为origin
$git push -u origin master //第一次提交的样子,后续提交只要git push完事了
//------subtree中
$git init
...............
...... git@github.com:xiongshaowen/subtree.git
......... "subtree init"
.......
二,parent通过subtree命令引入subtree库,引入子模块,这里我们要关联子模块了,首先给远程子模块起别名origin-subtree,方便后面的操作
--squash,会产生新的提交(很容易fast forward(不同分支追赶冲突)点,即fast forwar快进的前提条件是:两个分支提交点的父点是一样的。所以用--squash一定不要一会用,一会儿又不用,如下次更新时又不用--squash--------如$git subtree pull -P subtree origin-subtree master --squash。
//-------parent中
$git subtree //查询一下有多少操作
usage: git subtree add --prefix=<prefix> <commit>
or: git subtree add --prefix=<prefix> <repository> <ref>
or: git subtree merge --prefix=<prefix> <commit>
or: git subtree split --prefix=<prefix> [<commit>]
or: git subtree pull --prefix=<prefix> <repository> <ref>
or: git subtree push --prefix=<prefix> <repository> <refspec>
-h, --help show the help
-q quiet
-d show debug messages
-P, --prefix ... the name of the subdir to split out
//-P或--prefix它是关键的引入参数。意思引入进来进行区分开来。
//引入子模块,这里我们要关联子模块了,首先给远程子模块起别名origin-subtree,方便后面的操作
$git remote add origin-subtree git@github.com:xiongshaowen/subtree.git
$git subtree add -P subtree origin-subtree master
$git subtree add -P subtree2 origin-subtree master --squash //另一个方式引入子模块,parent中引入第二个子库,
//-P后的subtree,subtree2是子库名,origin-subtree是远程子库别名
//master是分支,即把远程,本地子库引入到本地和远程的父库中。
//--squash会减少提交次数,如子库subtree2提交了5次,但在父库中只看到一次提交,
//squash只一次提交是伪的,实际上有两次,先提交所有的(合并),再一次自已提交,往前走了两步
$git push //发布到远端,让远端也引入子库
三,本地修改子模块的b.txt,再提交发布后,再更新父库的子库并且再更新远端对应的子库操作如下:注意--squash参数的应用
//-----parent中
$git subtree pull -P sbutree origin-subtree master
//或
$git subtree pull -P subtree2 origin-subtree master --squash
//因为引入子模块到父库子模块subtree2是用了 --squash参数
$git push //发布更新到远端
四,修改父库中的子库,再更新真正的子库
如果是在网吧或在其它地方操作,某一天对同样的远端parent,subtree两库操作,可以先克隆到本地git clone ssh/https地址,再分别进入两个目录,不用git init初始化为版本库,但要再次引入子库操作,下面把远程子库关联进父库中:先起别名,再关联进来
$git remote add origin-subtree git@github.com:xiongshaowen/subtree.git
$git subtree add -P subtree origin-subtree master
修改父库中的子库b.txt,add . 提交,发布后,再更新真正子库的b.txt,再同步到远程。
一,修改parent下的subtree的b.txt,再add,commit,push
cd subtree
vi b.txt //输入parent
$git add .
$git commit -m "parent vi subtree"
$git push origin master //本次不用origin master,可直接push,
//但它只是更新了自已的,真正的subtree是不可感知
//要让其感知,则进入parent目录,再push一次
二,真正的子库subtree更新parent修改的subtree中的b.txt内容.直接pull是不行的.
//但它只是更新了自已的,真正的subtree是不可感知
//要让其感知,则进入parent目录,再push一次
//------------------parent本地
cd .. //假如当前在子库中,进入subtree的上一级目录
$git subtree push -P subtree oirgin-subtree master
//-------------subtree本地
$git pull
这样就同时更新真正子库远端,本地
五,subtree submodule冲突原理与解决
1.不同的祖先,合并时互相冲突。处理:vi 冲突的文件。
2.squash冲突,处理:发布和更新都要用squash参数。
cherry-pick-->commit转移
场景:写了一半(已提交),发现写错分支了,需要将已提交的commit转移分支等,cherry-pick每一次只转移一个点(本质是复制)。要频频使用git log命查commit sha1值。
//在需要commit点的分支中,转移
$git cherry-pick sha1值的4位---6位
把写错的分支与正确的分支同步
-----先在正确的分支上,cherry-pick sha1把错的分会提交点移到正确的分支上,然后,checkout sha,删除错分支的提交,再以正确的分支创建分支.
例:master为正确的分支,dev为错的分支.假设master已有a.txt文件,创建了dev分支,忘了切换回master,在dev上修改了两次a.txt,提交了两次,现在想做把写错的分支与正确的分支同步。
$git branch -b dev
$vi a.txt
$git add .
$git commit -m "first"
$vi a.txt
$git add .
$git commit -m "second"
//上面提交了两次
$git log
//查看所有提交的sha1值,事先复制放在一个文件中
$git checkout master
//切换到正确的分支上,准备转移
$git cherry-pick sha1_1
$git cherry-pick sha1_n
//.....有几个转移几个,从过云到现在顺序,但是sha1值变了,不是转移前的了,等于多了sha1值
$git checkout dev
//切换到dev删除提交点,
$git checkout sha1值--最好最初的合点sha1值 //回到写错之前的点
$git branch -D dev
//删除分支dev
$git branch -b dev
//创建dev分支,不用切换到master创建,因为最初创建分的点时,那个commit点是游离状态,游离状时,是创建分支的最好时机。
rebase:变基(衍合)相似cherry-pick
变基---改变分支基础
与cherry-pick操作的方向相反,它是在写错的分支里面可进行,并且不用一个一个的搞,很方便。
rebase会改变提交的历史。变基前的提交点会被遗弃。
rebase也会冲突
处理:1.vi xxx ---> add .--->git rebase --continue
2.忽略冲突 git rebase --skip
还原生成rebase之前的场景
git rebase --abort
建议
rebase分支,只在本机操作,不要推送到远程,不要在master上直接rebase.
举例:
先初始化一个库mygit,mygit里有一个文件a.txt,有一些容。
先在master分支中更改a.txt(第一行,制造后面的冲突)两次,提交两次,再创建dev分支,并切换到dev,也修改a.txt两次(也是修改第一行,造冲突),再在dev分支中git rebase master把dev所有提交移到master分支上(自动与最近一次提交点后接上)。
如有冲突,会出错,我们可以用以上三种方式处理冲突,按照上述做法有两次冲
1.若忽略冲突,可要执行两次git rebase --skip
2.vi a.txt,修改文件冲突 执行git rebase --continue
3.放弃变基git rebase --abort
touch a.txt
vi a.txt //输入一些内容,此时还是版本库
$git init //纳入版本库,初始化master,不初始化有问题
$git add .
$git commit -m "init"
$vi a.txt //改第一行
$git add .
$git commit -m "master1"
......
$git commit -m "master2"
$git checkout -b dev //创建dev分支,并进入dev
$vi a.txt
........................"dev1",,,,,"dve2"
$git rebase master //把dev的根基移到master上,
上面的事做完了,为了让master追上(快进)dev
$git checkout master //切换分支
$git merge dev //合并