在开发软件时,可能有多个人同时为一个软件开发,可能同时存在多个release版本,并且需要对各个版本进行维护,而git的分支功能就可以支持同时进行多个功能的开发和版本管理
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。
有一个问题是git怎么知道我们当前的代码在哪里呢?即使知道了代码在哪个分支上,又怎么确定在哪一个节点呢?我们是如何在git提交树上前后移动的呢?
git内部还有一个特殊的指针叫做HEAD。HEAD
指向的是现在使用中的分支的最后一次更新。
大多数修改提交树的Git命令都是从改变HEAD的指向开始的
如何查看HEAD:
cat .git/HEAD
ref: refs/heads/<branch name> // 正常
cad0be9ceb89f474c39360c4de337d4a8194cab0 // 游离状态
怎么分离head: 分离HEAD就是让其指向了某个具体的commit id而不是分支名。git checkot就是用来分离HEAD的
有两种分离方法:
git checkout
切换到任意分支,任意节点位置(通过commit id来确定节点位置)
git log
来查看提交记录的hash值checkout
后,git会从工作树还原向目标分支提交的修改内容,checkout之后的提交记录将被追加到目标分支。^
向上移动1个提交记录~
向上移动n个提交记录,比如~3
我们有两种分支:
/
的形式命名。对应的,我们有两种开发方式:
默认情况下:
(1)在远程开好分支,本地直接拉下来;
git checkout -b feature-branch origin/feature-branch //检出远程的feature-branch分支到本地
(2)本地开好分支,推送到远程.
$ git checkout -b developer_gen3_new_branch_name //在本地创建分支
$ git push --set-upstream origin developer_gen3_new_branch_name //推送到远程
创建并切换分支:
git branch + 分支名字
:创建分支
git checkout -b <分支名>
:创建并切换到新的分支在分支树上移动
git checkout<分支名>
: 切换到分支查看分支:
git branch
:
git branch -a
:查看全部分支(包含本地和远程)git branch -v
:查看每一个(本地)分支的最后一次提交 git branch --merged
:
git branch -d
删除掉:你已经将它们的工作整合到了另一个分支,所以并不会失去任何东西。git branch --no-merged
: 查看哪些(本地)分支还没有合并到当前(本地)分支
git branch --no-merged master
:查看当前未合并到master分支的有哪些? git branch --merged master
:查看当前已合并到master分支的有哪些?提交分支:
合并分支:
删除分支:
git branch -d [branchname]
:删除本地已合并的分支git push origin --delete [branchname]
:删除远程分支
git fetch -p
:清理本地无效分支(远程已删除本地没删除的分支)git branch | grep 'branchName'
:如果分支太多,还可以用此命令进行分支模糊查找默认情况下,我们在master分支,如果不切换分支的话,所有的操作都是在master分支上:
本来我们是master分支,然后我们执行下面命令
git branch testing
就会创建一个testing分支。此时两个分支都有相同的提交记录
这条命令做了两件事。
此时,我们位于master分支上,HEAD指向master分支的最后一次提交(通过HEAD指针知道我们位于哪一个分支上)
显示当前所有(本地)的分支:
不指定参数直接执行branch命令的话,可以显示分支列表。 前面有*的就是现在的分支。
$ git branch #显示当前所有(本地)的分支。 前面有*表示当前分支
iss53
* master # 这意味着如果在这时候提交,master 分支将会随着新的工作向前移动
testing
查看每一个(本地)分支的最后一次提交
$ git branch -v #查看每一个(本地)分支的最后一次提交
iss53 93b412c fix javascript issue
* master 7a98805 Merge branch 'iss53'
testing 782fd34 add scott to the author list in the readmes
查看哪些(本地)分支已经合并到当前(本地)分支:
$ git branch --merged
iss53
* master
查看哪些(本地)分支还没有合并到当前(本地)分支
$ git branch -d testing # 删除本地已合并的分支
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.
git commit作用
git commit 命令将暂存区内容添加到本地仓库中(基于当前分支生成一个快照,head指向最新的快照)。
提交消息可能存在很多拼写错误, 你想修改最近的commit的log,应该怎么办?
git log,可以查看提交历史
如果想要不同于默认格式的方式展示提交历史
--pretty
。选项有oneline
,short,full 和 fuller
git log --pretty=oneline
format
,可以定制记录的显示格式$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
%H | 提交的完整哈希值 |
%h | 提交的简写哈希值 |
%T | 树的完整哈希值 |
%t | 树的简写哈希值 |
%P | 父提交的完整哈希值 |
%p | 父提交的简写哈希值 |
%an | 作者名字 |
%ae | 作者的电子邮件地址 |
%ad | 作者修订日期(可以用 --date=选项 来定制格式) |
%ar | 作者修订日期,按多久以前的方式显示 |
%cn | 提交者的名字 |
%ce | 提交者的电子邮件地址 |
%cd | 提交日期 |
%cr | 提交日期(距今多长时间) |
%s | 提交说明 |
每次提交的简略统计信息
git log --oneline --decorate
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project
$ git branch -a # 查看全部分支(包含本地和远程)
* master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/master
$ git log remotes/origin/master # (origin/master这个都是默认的远程仓库和分支,可以自己改成想看的仓库和想看的分支)
$ git log remotes/origin/develop
当然如果你的本地很久没有更新过远程仓库的信息了,看到的日志可能就不是最新的;
所以在查看之前需要先运行git fetch 或者git fetch origin。
切换分支(git checkout)的本质是将head指向另一个提交记录,可以通过控制HEAD在分支树上移动。
步骤
$ git checkout issue1
Switched to branch 'issue1'
在当前分支上做一些修改
提交
$ git commit -m "添加add的说明"
原理
git checkout testing
为什么要git checkout 呢?
假设我们当前分支结构是这样的:
也就是说当前有master分支和testing分支,当前位于testing分支上。
假如我们做了一些修改,然后再次提交
$ git commit -a -m 'made a change'
此时,分支图如下:
然后我们切换回checkout
$ git checkout master
也就是说,你现在做修改的话,项目将始于一个较旧的版本。 本质上来讲,这就是忽略 testing 分支所做的修改,以便于向另一个方向进行开发。
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。
我们不妨再稍微做些修改并提交:
$ git commit -a -m 'made other changes'
现在,这个项目的提交历史已经产生了分叉
你可以在不同分支间不断地来回切换和工作,并在时机成熟时将它们合并起来。 而所有这些工作,你需要的命令只有 branch、checkout 和 commit。
实验
如下图Git仓库中: 当前正位于主分支main上,main分支最近一次提交记录为C1
- 那么,此时HEAD状态位于哪里呢?因为,HEAD通常情况下都是指向分支名的, 而分支名总是指向当前分支上最近一次提交记录, 因此,当前的状态为:HEAD->main–>C1,就是说,HEAD指向main,main指向C1
接下来,我们分离HEAD,分离HEAD就是让其指向了某个具体的commit id而不是branch name,执行命令
git checkout C1
。 此时“HEAD–>C1”
游离的HEAD指针:
git checkout <branch name>
git checkout <commit id>
此时看
git branch
* (HEAD detached at 925fda6) //此时head指向一个游离的状态
master
怎么解决?
git branch
* (HEAD detached at 925fda6)
master
git branch tem
git checkout tem
git checkout master
git merge tem
Updating cad0be9..2437c6b
Fast-forward
......
git push origin master
git branch -d tem
引用名称^
,表示让git寻找指定提交记录的父提交
如左图Git仓库中:
- 当前有三个提交记录:C0,C1,C3
- 当前只有一个main分支,而且main分支指向最近的一次提交记录
C3
- 也就是说HEAD—> main —>C3
接下来,我们执行命令
git checkout main^
,也就是说令HEAD
切换到main的父节点
命令
git checkout main^^
,意思是令HEAD
切换到main父节点的父节点
命令git checkout main^^^
,意思是令HEAD
切换到main父节点的父节点的父节点
…
我们也可以将
HEAD
作为相对引用的参照,如下图,指向命令:git checkout C3; git checkout HEAD^; GIT CHECKOUT HEAD^; git checkout HEAD^
如果我们要在提交树上走很多步的话,总不能敲^^^^^^^^^^
,因此引入了~
操作符
接下来我们看看效果
执行命令
git checkout HEAD~4
,后退4步
如左图所示, 当前分支位于bugFix上,因此状态为:HEAD–>bugFix—>C4
- 执行命令
git branch -f main HEAD~3
- 上面命令的意思是将main分支强制指向HEAD的第3级提交
不要用merge合并分支!!!!!!
如下图所示,bugfix分支是从master分支分叉出来的。
如果master分支的状态没有被更改过
因为bugFix分支的历史记录包含master
分支所有的历史记录
所以通过把master分支的位置移动到bugFix的最新分支上,git就会合并
执行合并时,如果设定了non fast-forward选项,即使在能够fast-forward合并的情况下也会生成新的提交并合并。
实践
$ git checkout master
$ git merge issue1
如果master分支的历史记录有可能在bugfix分支分叉出去后有新的更新。
实践
当前分支状态如下:
$ git merge issue3
Auto-merging myfile.txt
CONFLICT (content): Merge conflict in myfile.txt
Automatic merge failed; fix conflicts and then commit the result.
自动合并失败。
怎么办呢?
$ cat myfile.txt
first commit
add 把变更录入到索引中
<<<<<<< HEAD
commit 记录索引的状态
=======
pull 取得远端数据库的内容
>>>>>>> issue3
$ git add myfile.txt
$ git commit -m "合并issue3分支"
历史记录如下图所示。
理论
如下图所示,bugfix分支是从master分支分叉出来的:
如果使用rebase方法进行分支合并:
实践
合并issue3分支的时候,使用rebase可以使提交的历史记录显得更简洁。
$ git reset --hard HEAD~
$ git checkout issue3
$ git rebase master
。。。。
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
$ git add myfile.txt
$ git rebase --continue
Applying: 添加pull的说明
$ git checkout master
$ git merge issue3
当分支已经开发完毕之后,就可以删除分支了
$ git branch -d issue1
你可能正在开发一项新功能,由于太仓促,你忘记为它打开一个新的分支。这时候已经提交了大量文件,而且这些提交都位于主分支上。现在我们需要使用以下三个命令将所有这些更改回滚到新分支,注意:确保先提交或存储更改,否则一切都将丢失。
git branch feature-branch
git reset HEAD~ --hard
git checkout feature-branch
这将创建一个新分支,然后将主分支回滚到你进行更改之前的位置,然后最终检出你之前所有更改完整的新分支。
你可能错过了一个文件,忘了保存它,或者需要对最后一次提交做一个小改动。添加忘掉的文件,然后运行以下命令:
git add missed-file.txt
git commit --amend
此时,你可以修改提交消息,也可以只保存它以使其保持不变。
但是如果你做的恰恰相反呢?如果你添加了一个不想提交的文件,该怎么办?如果你所做的只是暂存文件但尚未提交,那就像重置该暂存文件一样简单:
git reset /assets/img/misty-and-pepper.jpg
如果你已经提交了这些改变,那也不用担心,只需要在之前执行额外的步骤,如下:
git reset --soft HEAD~1
git reset /assets/img/misty-and-pepper.jpg
rm /assets/img/misty-and-pepper.jpg
git commit
上述命令将撤消提交,删除图像,然后在其位置添加新提交。
git是一个分布式版本控制软件,分布式版本库的做法使源代码的发布和交流都极为方便,因此有不少用户都在使用git。最近小编也正在学习git这款软件,发现要想熟练运用git,学会git中的一些命令是很重要的,如果我们要回滚到某个提交,就需要使用到回退命令,下面小编给大家具体来介绍一下。
git回退到某个commit
git reset --hard HEAD^ 回退到上个版本
git reset --hard HEAD~3 回退到前3次提交之前
git reset --hard commit_id 退到/进到 指定的commit
git push origin HEAD – force 强退至远程
git回退到某个commit 推送远程
1.先查询对应的提交历史,使用如下命令:
2、版本回退,使用如下命令:
git reset --soft commitID //只删除commitID之后的提交记录log,代码的改动还在。
git reset --hard commitID //彻底删除commitID之后所做的改动,代码也一起回退回来了。(慎重用,用前最好备份一下代码,或者用git diff 生成一个patch)
3.把当前分支push到远程仓库并且让远程仓库和当前分支保持一致,使用如下命令(假定当前分支为master):
拉取特定的远程分支代码存在两种情形
1、git clone 指定远程分支
$ git clone -b dev https://gitee.com/xiaosheng/quartz.git
2、本地已有项目下拉取远程分支
$ git checkout -b developer_gen3_release origin/developer_gen3_release
push代码的时候,别人已经更新代码
error: 您尚未结束您的合并(存在 MERGE_HEAD)。
提示:请在合并前先提交您的修改。
fatal: 因为存在未完成的合并而退出。
1.error: 您尚未结束您的合并(存在 MERGE_HEAD)。
2.提示:请在合并前先提交您的修改。
3.fatal: 因为存在未完成的合并而退出。
解决办法