写在前面
文中用[ ]括起来的是变量,推荐使用图形化的git练习网站练习git的操作,更加的直观传送门
提交
git commit
新建分支
git branch [branch_name]
切换分支
git checkout [branch_name]
新建并切换分支
git checkout -b [branch_name]
合并分支
# 在main分支上合并bugfix分支
git merge bugfix
注意:
- 如果处于父节点上merge子节点,则head直接跳到子节点,因为子节点拥有父节点所有的修改。
- merge会创建一个新的节点,head移动到新节点
移动HEAD到上一个提交
我们使用checkout来移动HEAD,这里看看如何使用相对位置
git checkout main^ // 移动到main的父节点
git ckeckout main^^ // 移动到main的父父节点
如果要移动到当前HEAD的父节点,可以使用下面的方法
git checkout HEAD^
移动HEAD到上三次提交
git checkout HEAD~3
移动分支
上面我们看到了移动HEAD,移动了HEAD之后,分支仍不变,我们同样可以移动分支
git branch -f main HEAD^ //移动main分支到HEAD的上一个节点
回退到某节点(不删除修改)
常用于本地分支的回退
使用reset命令使得HEAD回退到某一个节点,此操作不会删除已经做好的修改
git reset HEAD^ //回退到HEAD的上一次提交
注意这里后面加的是需要回退到的节点名称
回退分支并产生一个提交
常用于远程分支的回退
使用revert命令回退分支的一个修改,此操作会添加一个提交
git revert HEAD
- 注意这里后面加的是需要回退的节点,而不是回退到的节点
- 注意在回退的时候,要注意自己所处的节点,处在什么节点,revert之后产生的节点就在那个所处的节点之下
提取某几个节点的修改
在main分支上,把另外几个分支的好几个节点的修改拉到当前分支
git cherry-pick c1 c2 c3
在main分支上运行这个命令,会在main分支上产生c1 c2 c3三个提交记录,将这三个节点的数据都拿出来
使用交互式窗口,重新调整一些提交的去留和顺序
git rebase -i HEAD~4
这个命令会让我们使用vim,来调整四次提交的顺序,可以只提取其中的三个,也可以调整提取节点的顺序
git rebase -i c1 //提取目前位置到c1的全部提交,进行去留的决定和顺序的调整
修改上一次提交
git commit --amend
打Tag
分支容易改变,Tag不易改变
git tag v1 //在当前HEAD当前的位置上打一个Tag
git tag v1 C1 //在C1这个提交上面打一个Tag
查看tag
git describe [提交的hash或者HEAD,分支头]
<tag>_<numCommits>_g<hash>
tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位
提交修改
// 基于HEAD推送
git push
// 不管HEAD在哪里,自己在哪个分支,我都要推送master分支到origin(本地已经设置了master之于远程分支的关联)
git push origin master
// 将本地的foo分支推送到远程的main(目标分支不存在git回自动创建)
git push origin foo:main
拉取远程代码
- fetch 只拉取远程节点,不修改本地代码
- pull = fetch + merge
- git pull --rebase = fetch + rebase
git fetch也可以像push那样添加参数
// 将远程main的前一次提交,拉到本地foo分支上
git fetch origin main^:foo
注意,fetch和push,冒号两边的顺序是相反的,但是逻辑都是 从…到…
同理,pull也可以同样的使用指定origin和使用冒号指定源和目标。
设置远程关联
在下载一个分支的时候,git会创建一个本地的main一个远程的origin/master,并且内部设置这两个分支的关联,但是这种关联关系不是不可修改的
// 新建一个newbranch分支,他的远程分支事origin/main
git checkout -b newbranch origin/main
或者使用下面的命令
git branch -u newbranch origin/master
删除远程分支
// 删除远程的foo分支
git push origin :foo
补充知识
rebase和merge
相同点:
- 两者都用于合并分支
不同点: - merge是把另一个分支的修改拉过来,然后在自己的基础上创建一个新的节点。rebase是把自己的修改给另一个分支,在另一个分支的基础上创建一个新的节点
- rebase的提交记录更加线性
# 在main上
git merge bugfix //把bugfix分支上的修改拿来,并在自己的分支下面产生一个节点
git rebase bugfix // 把自己的修改给到bugfix,在bugfix下面产生一个节点
从优缺点上来说:
- merge更能保留提交的记录
- rebase让提交树更加的清楚
与分支分离的HEAD
在我们普通的使用中,可以看到命令行中main*的提示,这表明目前的头节点指向了main分支
头节点不一定非要指向分支,还可以指向提交记录(也就是某一个节点),同样需要使用checkout命令
git checkout [branch_name] // 切换分支
git checkout [提交的哈希] //切换HEAD到某一个提交
相对位置和绝对位置
在移动的时候,我们可以使用相对位置和绝对位置移动
- 绝对位置:节点的哈希值(每次提交的哈希值)
- 相对位置:^往上一个 ~3往上三个 ,相对位置的锚点可以相对HEAD,相对分支,也可以相对某一次提交的哈希值
^标识父节点 ^2标识如果一个提交有多个父节点的时候另一个父节点
commit多次之后,发现其中某一次提交需要修改
当我们遇到这个问题的时候,我们可以用下面的思路
- 使用git rebase -i 命令,重排commit,将需要修改的commit放到树的最下面
- 使用git commit --amend修改最后一次提交
- 再次使用 git rebase -i 排序commit
相对位置的级联使用
git checkout main^2~3
标识跳转回main的第二个父节点的往前三个节点
远程分支
如果关联了远程仓库,本地会有一个main游标,还会有一个origin/main游标。
当我们执行 git fetch 的时候,远程游标会更新到远程最新状态,但是本地文件都不变。
当我们运行 git checkout origin/main 的时候,git将HEAD指向origin/main游标。
checkout和merge
在移动游标的时候,我们需要注意,当我们使用checkout + 提交哈希 的时候,移动的是HEAD,如果我们想移动当前的分支游标,需要使用 reset merge rebase