workspace :工作区;Index :暂存区;Repository :本地仓库;Remote :远程仓库;
命令学习建议去网站https://learngitbranching.js.org/?locale=zh_CN学习,形象生动!!
放入暂存区,本地仓库
git add命令,实现将项目放入暂存区;
git commit命令,实现将项目放入到本地仓库;
git push命令用于将本地分支的更新,推送到远程主机。
git push <远程主机名> <本地分支名>:<远程分支名>
#远程仓库别名默认为origin(我们在上一章节提到过修改方法,这里不做解释)
#远程分支别名待我们自定义,如果想和本地分支名称一样的话,那就不需要添加 :远程分支别名
git push origin master
#上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。
拉取
git fetch:把远程分支拉到本地:git fetch origin dev(dev为远程仓库的分支名)
git clone:项目的拷贝,执行命令:git clone git://git.kernel.org/pub/scm/git/git.git(远程仓库地址)
git pull是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。
查看提交详情
git log 查看所有的commit提交记录
git show 查看提交的详情
## 1.查看最新的commit
git show
## 2.查看指定commit hashID的所有修改:
git show commitId
## 3.查看某次commit中具体某个文件的修改:
git show commitId fileName
撤销提交
git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset 命令格式为git reset --soft | --mixed | --hard <commitId>
## 参数soft、 mixed、hard,它们告诉Git,当执行reset时,要对index和working copy做什么。
git revert
git reset三种模式,每一种模式对应的操作的细节如下:
git reset三种模式区别和使用场景
区别:
–hard:重置位置的同时,直接将 working Tree工作目录、 index 暂存区及 repository 都重置成目标Reset节点的內容,所以效果看起来等同于清空暂存区和工作区。
–soft:重置位置的同时,保留working Tree工作目录和index暂存区的内容,只让repository中的内容和 reset 目标节点保持一致,因此原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files)。所以效果看起来就是工作目录的内容不变,暂存区原有的内容也不变,只是原节点和Reset节点之间的所有差异都会放到暂存区中。
–mixed(默认):重置位置的同时,只保留Working Tree工作目录的內容,但会将 Index暂存区 和 Repository 中的內容更改和reset目标节点一致,因此原节点和Reset节点之间的【差异变更集】会放入Working Tree工作目录中。所以效果看起来就是原节点和Reset节点之间的所有差异都会放到工作目录中。
使用场景:
–hard:(1) 要放弃目前本地的所有改变時,即去掉所有add到暂存区的文件和工作区的文件,可以执行 git reset -hard HEAD 来强制恢复git管理的文件夹的內容及状态;(2) 真的想抛弃目标节点后的所有commit(可能觉得目标节点到原节点之间的commit提交都是错了,之前所有的commit有问题)。
–soft:原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files),所以假如我们之前工作目录没有改过任何文件,也没add到暂存区,那么使用reset --soft后,我们可以直接执行 git commit 將 index暂存区中的內容提交至 repository 中。为什么要这样呢?这样做的使用场景是:假如我们想合并「当前节点」与「reset目标节点」之间不具太大意义的 commit 记录(可能是阶段性地频繁提交,就是开发一个功能的时候,改或者增加一个文件的时候就commit,这样做导致一个完整的功能可能会好多个commit点,这时假如你需要把这些commit整合成一个commit的时候)時,可以考虑使用reset --soft来让 commit 演进线图较为清晰。总而言之,可以使用–soft合并commit节点。
–mixed(默认):(1)使用完reset --mixed后,我們可以直接执行 git add 将這些改变果的文件內容加入 index 暂存区中,再执行 git commit 将 Index暂存区 中的內容提交至Repository中,这样一样可以达到合并commit节点的效果(与上面–soft合并commit节点差不多,只是多了git add添加到暂存区的操作);(2)移除所有Index暂存区中准备要提交的文件(Staged files),我们可以执行 git reset HEAD 来 Unstage 所有已列入 Index暂存区 的待提交的文件。(有时候发现add错文件到暂存区,就可以使用命令)。(3)commit提交某些错误代码,或者没有必要的文件也被commit上去,不想再修改错误再commit(因为会留下一个错误commit点),可以回退到正确的commit点上,然后所有原节点和reset节点之间差异会返回工作目录,假如有个没必要的文件的话就可以直接删除了,再commit上去就OK了。
新提交记录 C2’ 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。也就是说 C2’ 的状态与 C1 是相同的。
a. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
b. 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
c. git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。
1.进入到settings中,找到Branchs,如图点击箭头
2.切换即可
1.查看分支
在创建分支前,我们需要学会怎样去查看现有的分支:
git branch
#查看当前Git仓库中所有分支列表
2.创建分支
接下来我们创建一个自定义名称的分支:
git branch 分支名称
#基于当前所处的分支(我当前在main主分支中)创建了一个自定义名称的分支
#此时新分支中的代码和当前所处分支代码相同
tips:我们创建完成之后,会多出来一个新的功能分支,但是不会默认的切换到该分支,也就是说,我们现在还身处于main主分支中
3.切换分支
git checkout news
#切换到指定分支上
创建的同时切换到新功能分支上
git checkout -b 分支名称
#创建指定名称的分支并且立即切换到新分支上
4.合并分支
当我们的功能分支开发并测试完毕之后将会合并到主分支上,形成一个完整的项目或模块
我们刚才的切换到了news分支上,不在主分支,所以我们还不能直接进行合并,需要先切换到主分支:
git checkout main
git merge news
#在main主分支上将指定功能分支进行合并
5.删除分支
好了,现在我们合并完成,那这个功能分支也就没用了,我们过河拆桥,删除掉它:
git branch -d 分支名称
#删除对应分支,但是如果这个分支没有合并的话,会报错,不让你删
git branch -D 分支名称
#强制删除对应分支,就算没有合并也会强制删除
tips:我们不能处在要删除的分支上,我们应该先切换到其他分支,然后再删除,我们要做的是过河拆桥,千万不要把自己也搭进去了
6.遇到冲突时我们应该怎么进行分支合并
假如在俩个不同的分支中,对同一个文件进行了不同的修改,那么我们合并的时候就会出现冲突,Git不明白我们需要怎么操作,所以没有办法合并它们,此时,我们可以手动操作打开这些包含冲突的文件,根据实际需求删除或者修改代码,来解决冲突。
1.本地分支同步推送到云端远程仓库
git push -u 远程仓库别名 本地分支名称:远程分支别名
#远程仓库别名默认为origin(我们在上一章节提到过修改方法,这里不做解释)
#远程分支别名待我们自定义,如果想和本地分支名称一样的话,那就不需要添加 :远程分支别名
#只有第一次同步推送才会使用上面的指令,以后我们可以直接使用:
git push
2.查看远程仓库所有分支列表
git remote show 远程仓库名称
3.跟踪分支
我们想要把远程仓库中的分支下载到本地仓库中(可能一个人开发是不会用到,但是多人协作开发时非常的常用):
git checkout 远程分支名称
git checkout -b 本地分支名称 远程仓库名称/远程分支名称
#下载到本地并把下载的分支进行重命名(只是在你的本地重命名)
4.拉取远程分支最新文件内容
拉取当前分支在远程仓库的最新代码或内容,保持当前分支文件和远程分支文件一致
git pull
tips:需要切换到当前分支才可以进行此操作
5.删除远程仓库指定分支
git push 远程仓库名称 --delete 远程分支名称
当刚加入到一个的项目组,我们怎样获取项目组github的代码以及新建分支,push分支,merge分支呢?
首先下载git bash,配置公私钥,没有提前配置的可看另一篇博客。即可使用以下流程(注意git项目你是被invitation了的即你有操作的权限)。
总体流程:
## 新建一个放项目的文件夹,在文件夹下打开命令行窗口git clone项目
git clone 仓库的地址
## 先创建自己的分支,然后本地开发,本地开发完后,先将改动推送到自己所在的的远程分支bra
git checkout -b bra
## ...coding
## 进行代码的编写及修改,修改完后:add到暂存区,commit到本地仓库,push到运程仓库自己的分支
git add .
git commit -m "修改xxx"
git push origin bra
## 然后自己的分支合并到master:首先本地仓库切换到master主分支,将最新的远程分支master拉到本地,保持最新
git checkout master
git pull origin master ## 这一步的目的在于如果在进行本分支修改时有其他分支进行了分支合并,那我们就必须去拉取最新的
## 本地分支bra合并到本地的master分支上
git merge bra
## 将本地的master分支推送到远程的master分支上
git push origin master
## 扫尾,切换回本地的仓库分支bra,以及拉取最新的master
git checkout bra
git pull origin master
比较正规的流程详解:
主分支master只用来分布重大版本,日常开发应该在另一条分支上完成。我们把开发用的分支,叫做dev。
一般在工作中使用较多的为分支模型为生产/开发模型,即master/dev类型分支。团队开发成员一般是对于dev分支进行提交。
模拟多人协作开发:(默认分支已设置为dev)
现在有两个开发者A和B,两个开发者都要在自己的分支上进行独立的开发。
1.创建分支
开发者A在接到开发任务的时候,先将项目clone到自己本地 在gitbash执行命令:git clone [项目git地址]
此时应该处于默认分支:dev分支
开发者A应该在自己的分支进行开发,所以先创建属于自己的分支:
git checkout -b A(创建并切换到A分支) ,这条命令其实是下面两条命令的缩写
git branch A #创建A分支
git checkout A #切换到A分支
这个时候,开发者A 可以在自己的A分支上开始工作!
开发者B操作同上
2.分支合并
两个开发者分别在自己的分支上进行开发。当然,两个开发者完成任务的时间一般是不一样的。
现在开发者A最先完成任务,他需要将自己的A分支合并到dev分支。(如果要把自己的分支推到仓库使用git push origin A)由于在开发者A之前没有人向dev分支push内容、合并分支,所以开发者A执行以下命令即可:
git checkout dev #切换到dev分支
git merge A #将A分支合并到dev分支
这样,开发者A就成功将自己的分支合并到dev分支了。
但是:分支合并是在本地进行的此时git线上仓库其实是没有合并的,所以记得将在本地合并好的dev推送到远程
git push origin dev
这样,远程仓库的dev就已经是合并好的了
现在开发者B完成开发了(如果要把自己的分支推到仓库使用git push origin B),需要将B分支合并到dev分支。
同上,先切换到dev分支:git checkout dev
但是,此时的dev分支已经和远程的dev分支不同步了,所以需要先将本地的dev分支与远程仓库的dev分支进行同步
git pull origin dev
然后再进行合并git merge B
可以看到命令行提示:Automatic merge failed; fix conflicts and then commit the result
这个时候,就需要解决合并冲突了:
使用命令:
git status
可以看到需要解决冲突的文件,可以选择保留一方更改或者保留双方更改,这个过程需要手动
解决完冲突后提交更改
## 先切换到分支上
git checkout bra
## 使用rebase命令把自己的commit信息复制到master分支上
git rebase master
图解:
master上有一个新提交M,feature上有两个新提交C和D
此时切换到feature分支上,执行如下命令,相当于是想要把master分支合并到feature分支(这一步的场景就可以类比为我们在自己的分支feature上开发了一段时间了,准备从主干master上拉一下最新改动)
下图为变基后的提交节点图
feature:待变基分支、当前分支
master:基分支、目标分支
当执行rebase操作时,git会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。
使用场景:
拉公共分支最新代码的时候使用rebase,也就是git pull -r或git pull --rebase。这样的好处很明显,我用rebase拉代码下来,但有个缺点就是rebase以后我就不知道我的当前分支最早是从哪个分支拉出来的了,因为基底变了嘛。
往公共分支上合代码的时候,使用merge。如果使用rebase,那么其他开发人员想看主分支的历史,就不是原来的历史了,历史已经被你篡改了。举个例子解释下,比如张三和李四从共同的节点拉出来开发,张三先开发完提交了两次然后merge上去了,李四后来开发完如果rebase上去(注意李四需要切换到自己本地的主分支,假设先pull了张三的最新改动下来,然后执行,然后再git push到远端),则李四的新提交变成了张三的新提交的新基底,本来李四的提交是最新的,结果最新的提交显示反而是张三的,就乱套了。
正因如此,大部分公司其实会禁用rebase,不管是拉代码还是push代码统一都使用merge,虽然会多出无意义的一条提交记录“Merge … to …”,但至少能清楚地知道主线上谁合了的代码以及他们合代码的时间先后顺序
相同点:都可以合并代码
不同点:
1.通过merge合并分支会新增一个merge commit,然后将两个分支以前的commit记录都指向这个新的commit,是一种非破坏性的操作,保留之前的每个分支的commit,现有分支不会被更改,但是会导致历史记录相对复杂
2.rebase会先找到两个分支的第一个共同的commit祖先记录,提取在这之后的所有commit记录,将这些记录添加到目标分支的最新提交后面,变成了线性的记录,有效整合所有分支上的提交;主要好处是历史记录清晰,是在原有提交的基础上将差异内容反映出来,消除了git merge带来的不必要的合并提交。
3.rebase操作后会丢弃当前分支已经提交的commit,所以不要在已经push到远程以及和其他人正在协作开发的分支上执行rebase操作。
git pull做了两个操作分别是‘获取’和合并。所以加了rebase就是以rebase的方式进行合并分支,默认为merge。
参考:
https://blog.csdn.net/ThirteenC/article/details/106710684
https://www.jianshu.com/p/c2ec5f06cf1a
https://blog.csdn.net/weixin_42310154/article/details/119004977