git 常用点,详解
from my typora
文章目录
这一类: git add、git commit 、git push、git status、git init
但是注意第一次初始化本地库,最好用git clone,强调,不要git init git pull。
再补充一下,其实pull = merge + fetch
包括 git config user.name 、git config user.email 以及–global参数。
我就跳过了
保存现场:https://blog.csdn.net/qq_36791569/article/details/82716694
git 模式解析
git中,几大空间,依此的关系,分别是:
工作区 — 暂存区 — 本地库 — 远程库
工作区:就是写代码的地方;
暂存区:是一共中转站,通过git add 到达;
本地库:一个比较稳定的地方了,add之后,通过commit到达。
远程库:通过push、pull进行交互。
其中几种撤销我就略过了:比如工作区修改撤销,暂存区修改撤销,比较鸡肋,有兴趣看这两段话:
删除文件
方式一:
rm test.txt 先删除工作区的test.txt
git add test.txt (我的理解是,将删除test.txt这个动作add上去,告诉本地版本库)
git commit -m “删除了test.txt”
方式二:
rm test.txt 先删除工作区的test.txt
git rm text.txt 提交一个git动作,删除本地版本库中的text.txt但是只是记录了动作,还没有commit提交到本地的版本库中
git commit -m “删除了test.txt”
远程库
# 增
# 添加远程库
# 不一定要叫origin,只是我们习惯叫origin,下同!
git remote add origin https://gitee.com/yaoguai1998/LearnGit.git
# 删
# 删除远程库
# 远程库库名叫什么,就删什么!
git remote rm origin
# 查
# 查看所有远程库的缩略信息
git remote
# 查看所有远程库的完整信息
git remote -v
# 改
# 改变远程库的url,这里写的是git@为ssh协议,不是http协议,但是均可
git remote set-url origin git@gitee.com:yaoguai1998/LearnGit.git
配置忽略文件
在我们协同的时候,经常因为项目中的一些.class文件,target目录,.project一类类似的文件冲突,这种东西我们要让git去忽略它,不进行同步
- 首先准备一个忽略文件(*.gitignore)
# Java.gitignore,随便放哪里,我放在用户家目录下的
# Java.gitignore:文件名随便取
# Java.gitignore文件内容如下
# -------------------
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.factorypath
.classpath
.project
.settings
target
jdbc.properties
# -------------------
- 单库方式
# 找到当前本地库文件夹中的.git文件夹
# 打开其中的config文件
# 添加以下内容
[core]
# 这个是你的gitignore文件的路径,因为我是放家目录的
excludesfile = C:/Users/Administrator/Java.gitignore
- 全局方式
# 到用户家目录下,找到.gitconfig文件
# win在 C:Users(用户组)Administrator(当前用户目录) 下
# ubuntu一类linux,在 /home/用户/ 下
# 同样添加以上内容
[core]
# 这个是你的gitignore文件的路径,因为我是放家目录的
excludesfile = C:/Users/Administrator/Java.gitignore
查看版本库日志,以及版本回退
git log
# 空格向下翻页,b向上翻页,q退出
git log # 显示所有日志的所有信息,较多并且较为繁琐
git log --pretty=oneline # 以较好的格式输出 两个斜杠
git log --oneline # 显示简略信息 两个斜杠
推荐使用:git reflog 显示简略信息,但是相对于上面直接的 git log –oneline多了一个head移动步数,推荐使用这种:git reflog
# 最推崇的方式:
git log --graph --pretty=oneline --abbrev-commit
查看日志 分支合并图 一行显示 缩减commitId的长度
git log --graph --pretty=oneline --abbrev-commit
版本回退:
# 别记那么多,版本回退就用 git reset --hard 版本号
git reset --hard c17e52f # [c17e52f:是局部索引值]可以回退到特定的版本
解决冲突
在我们进行分支合并的时候,本地两个分支:
1.切换到我们需要合并的分支上。
2.进行merge操作,如果没有冲突则会直接成功,如果出现冲突,则会:
git 是一个好工具,就是门槛比较高。
<<<<<<< HEAD
这是我在master上add,commit的内容
=======
这是我在mzy上add,commit的内容
>>>>>>> mzy
可以看出git在这种无法自动处理的冲突上,使用了
<<<<<<<
=======
>>>>>>>
进行标识
<<<<<<<HEAD:固定的表示当前HEAD指向的,不一定是master。
=======:用于冲突之间分隔
>>>>>>>:被合并分支名称
内容一定是当前分支在HEAD下,被合并分支在后面。
手动修改这些文件,去掉其中的分隔符号,并且把内容修改成你想要的样子,
再次 git add readme.txt,git commit -m "合并分支mzy,并且解决了冲突"
我们可以让日志显示格式改一改,看到其中的合并步骤:
git log --graph --pretty=oneline --abbrev-commit
* 3b15b8e (HEAD -> master) conflict fixed
|
| * dbee345 (mzy) AND simple
* | b1d6af5 在主分支上进行提交
|/
* fd4ceae 修改了readme.txt文件
* c5687b8 删除test.txt[C
* b71048d 提交test.txt
* 88726c9 提交了readme.txt中的修改
* e4deff9 git change readme.txt add tracks change of files
* 9a3670d add LICENSE to res
* c3e7dc7 加上了GPL
* c17e52f 加上了一些新玩意儿distributed
* 9f6ffb9 第一次提交readme.txt
合并之后,怎么让另一个分支也享受被合并的愉悦呢?(因为我们分支合并只能体现在当前分支,被合并分支不能体现出来)
你应该反过来想,既然已经合并, 为什么不把原来的分支删除了,按照新分支的样子创建一个新的分支呢?在当前分支的基础上?这样不就行了吗?
替换我们常用的直接merge的方式:
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息(即:原来这个分支的做了什么在log中体现不出来)。
为了让我们的版本库更清晰,我们可以使用普通合并方式:
# 普通合并
git merge --no-ff -m "把dev分支上的内容合并到master上,使用普通合并" dev
git merge --no-ff -m "把dev分支上的内容合并到master上,使用普通合并" dev
$ git log --graph --pretty=oneline --abbrev-commit
* 8fc444b (HEAD -> master) merge with no-ff
|
| * 1601be9 (dev) add merge
|/
* 4aa96bc 修改了readme.txt
* 68f4f31 修改LICENSE
* 6653ea8 Merge branch 'yao' into mzy
分支处理
创建分支:
# 如何创建一个本地分支?
# git branch 分支名
# 例如创建一个dev分支
git branch dev
# 注意噢,如果不带参数,就是查看当前有多少分支
$ git branch
dev
master
tb1
* tb2
# 但是以上的方式,只能创建分支,不能切换到创建的分支上
git checkout -b dev # 不仅创建了dev分支,并且切换到了dev分支上
# 如上就引出了,切换分支的命令
# git checkout 分支名
git checkout mzy # 切换到mzy分支上
删除一个本地分支呢?
# 上面讲了创建一个分支 直接:git branch 分支名
# 删除的话,就是git branch -d 分支名
git branch -d dev # 就删除了dev分支
# 注意以上只能删除本地的分支,不能删除和本地库有关的远程库的分支
# 删除远程库的分支的命令,以下会讲
新概念,追踪(track)关系,前引:
在git远程库和本地库中,我们的分支经常是一一对应的,(这种对应可以名字不同),其实他们物理意义上不是一一对应的,只是在我们看来是一一对应的!
为什么呢?
你发现没有,当你推送的时候:
即使本地有一个master,远程有一个master
本地有一个dev,远程有一个dev
你推送的时候,还是通过
push origin master、push origin dev
pull origin master、pull origin dev
但是如果有追踪关系的话,你在当前分支(如dev分支)上
你直接git pull 、git push
git 就会直接帮你pull 或者push 对应到远程库上的分支!
这种关系,我们叫做追踪:
追踪关系有两种使用场景:
**1.当前本地库有一个分支,但是远程库没有 **
2.当前远程库和本地库,都存在这个分支,但是没有关联起来,希望强关联
如果当前git远程库中,没有当前的本地分支(或者要和远程库中的分支建立追踪关系的时候):
# 方式一:
git push --set-upstream origin mzy
# 方式二:
# 注意在有些场景下我们用:远程仓库名/分支名,代表远程库上的分支
git branch -u origin/mzy
# 解除追踪关系
git branch --unset-upstream
# 查看是否有追踪关系
git branch -vv
# 这种就是有追踪关系
dev 5631865 [origin/dev: ahead 2, behind 3] dev提交
master cfd7d4e [origin/master] 删è提交
* tb1 6ee4ba4 [origin/tb1] test3上提交
# 这种就是没有追踪关系
tb2 6ee4ba4 test3上提交
test1 729034d [origin/test1] test1提交
test2 d352291 [origin/test2] test2提交
test3 6ee4ba4 [origin/test3] test3上提交
删除一个本地分支后,并且删除一个远程分支:
# 首先要确定你现在所在的分支不是你要删除的分支!!!不然无法删除
# 首先切换到任意一个非你要删除的分支上
git branch -d tb2 # 删除的参数可以是
git push origin :tb2
如果需要强制覆盖远程的一个分支怎么办?
git push --force origin master
git push -u origin master -f
如果要强制用远程分支覆盖本地的分支怎么办?
git fetch --all
# 注意在有些场景下我们用:远程仓库名/分支名,代表远程库上的分支
git reset --hard origin/master
git pull
当你进行pull的时候,远程库告诉你 fatal: refusing to merge unrelated histories
原因是git判定你的远程库和本地库的分支的内容不相干,所以拒绝了你的合并,如果你执意要的话,请:出门右拐执行
git pull origin master --allow-unrelated-histories
协同最好的方式
我们约定的开发方式,请大家遵守:
首先我们有一个稳定版本(master),基于master产生一个开发版(dev),在开发版的基础上,我们衍生出各个开发者各自的分支:huchao、wanglanlin、yangtao …
1.自己的电脑上只能有自己的分支和dev分支,不随便拉别人的分支。
2.每天或者一段时间代码写完之后,记得提交到远程库的自己分支上。
3.在要往dev上合的时候,commit中的信息必须写清楚,修改了什么文件,以及原因;或者增加了什么功能
4.在往远程库的dev上合并新代码的时候,记得群里告知大家去pull远程库的dev,以及尽快合并到自己的分支上,防止版本库堆积。(或:养成经常pull origin dev的习惯)
5.阶段性dev提交的时候(即全部统一的时候:我称为里程碑),我们约定:此刻我会删除当前远程库上的所有除master、dev以外的所有分支,请大家也删除自己本地的个人分支,以当前的dev分支为模板创建一个新的分支。
# 1.每天工作结束,提交代码到远程库的自己分支上
# 在添加了忽略文件的前提下
git add ./*
git commit -m "提交了xxx"
# 如果设置了以上的追踪关系,直接 git push
git push origin mzy(分支名)
# 2.阶段任务完成,增加更新,提交到dev上
# 为了确保无误,先从远程库pull一次
git pull origin dev
# 然后切换到dev分支上,把自己分支的内容合并上去
git checkout dev
git merge mzy
# 没有冲突,直接fast-forward了
# 如果有冲突,则手动合并,参照上
# 合并完成,add commit push
git add ./*
git comit -m "合并到dev,一定要写清楚合并了什么"
git push origin dev
# 然后删除当前的个人分支,参照新的dev,创建个人分支
# 注意一下操作确保是在dev分支上的!
git branch -d mzy # 删除mzy分支
git checkout -b mzy # 按照当前的dev分支建立mzy分支,并切换到mzy分支
# 以上过程稍微显得有点繁琐,但是因为昨天我测试无法跨分支推送,即只能先这样
# 也是我请教师兄之后,告诉我的方法。
# 最初我是向跨分支推送的,因为原来可以,比如直接把mzy -> push origin dev
# 但是不行,大家解决之后,请告诉我,我们一起优化!
# -----------------------------------------------------
最开始我的想法:(但是没有实现,期待大家一起解决)
问题一
我现在在远程库上有master、dev、dev1、dev2。
dev1和dev2是基于dev创建的,我希望他们本地都只存留dev1、dev2这一类的个人分支,合并的时候,先pull origin dev,如果有冲突,在本地merge了,这一步是能够实现;但是当我想要在dev1上向远程dev分支上推的时候就出错了,只能向远程的dev1上推送,不能向远程的dev上推送。即使我使用push origin -u dev -f 也不行,说everthing up to date,难道当远程分支dev1和本地分支dev1建立了关系,就不能跨分支推送了吗?为了印证这个猜想,我unset-upstream 解除了远程分支dev1和本地分支dev1的追踪关系,但是解除之后仍然不能把已经merge了远程分支的dev1推向远程的dev,所以我不知道我的问题出在哪里了?