Git的基础使用
分支
merge
存在两种merge操作,分别为fast-forward(--ff
)和no-fast-forward(--no-ff
).
前者默认发生在当前分支没有相对于待合并分支的额外结点时,此时不会发生新的commit,只是向前移动当前分支指针。
后者默认发生在其他情况下,此时会产生一个新的commit,其拥有两个父结点,分别位于两个分支中。如果出现冲突还需要手动解决。
rebase
rebase将当前分支的提交复制到另一分支之后。此过程中,被复制的commit会重新生成hash值.
interactive rebase可以以当前分支中的commit为参数,并且可以对需要复制的commit进行修改.
cherry-pick
git cherry-pick [commit id]
在当前分支下新增一个commit,其内容与指定的commit相同.
HEAD
HEAD
指针是一个symbolic
reference(符号引用,快捷方式),指向分支名或者一次commit.
通常情况下HEAD
总是指向分支名,这意味着其指向当前分支最近一次commit.
git checkout [commit id]
分离头指针使其指向某次commit而非分支名(commit用其hash值指定,且仅需前6位).
cat .git/HEAD
查看当前HEAD指向.
git symbolic-ref HEAD
查看当前HEAD指向(仅限HEAD指向分支名时,即HEAD->master->Commit_1)
相对引用
使用^表示指定引用的父节点,如HEAD^
master^
使用~<num>
表示向上移动多次,如HEAD~3
配合git branch -f [branch name] [ptr]
强制移动(非当前)分支指针位置,如git branch -f master HEAD~3
撤销变更
git reset [ptr]
将当前分支HEAD移动到指定位置,如git reset HEAD^
.从新位置到旧位置之间的提交仍存在,处于未加入暂存区的状态;但是如果使用--hard
参数,这些提交会消失.这种方式往往应用于个人维护的分支.
git revert [ptr]
以添加一个新commit的形式撤销ptr指向的提交,因此添加新提交后的状态与ptr的父节点相同.这种方式往往应用于多人协作分支,因为它不会导致提交历史的改变.
标签
鉴于分支可以轻易地被移动和更改,引入了tag的概念。tag是一个永久指向某个提交记录的标识,不会随着新的提交而移动.git tag [tagname][ptr]
将名为tagname的tag打在ptr指向的commit上.
git describe [ptr]
返回离ptr指向的commit最近的tag,格式为<tag>_<numCommits>_g<hash>
,其中<tag>
是离ptr最近的标签,<numCommits>
表示ptr与这个标签之间相差多少个commit,<hash>
是ptr指向的commit的hash值.
reflog
git reflog
展示分支的操作历史,可以配合git reset
实现撤销操作。
远程分支
远程分支位于本地仓库中,反映了最后一次与远程仓库通信时的状态。
远程分支的命名规范是<remote name>/<branch name>
,默认的远程仓库名是origin
.
远程分支在成为checkout
的目标时会自动进入分离HEAD状态,这是为了让远程分支不能成为直接操作的对象。
git clone
时会自动为远程仓库中的每一个分支,在本地仓库中创建一个远程分支并加以关联。
git fetch origin master
从远程仓库下载本地缺失的提交记录并移动本地的origin/master
远程分支指针;本地仓库不会发生改变,即master
分支不变,文件不会被修改。
不带参数的git fetch
将各commit下载到对应的分支里。
git pull
相当于git fetch
加上git merge
,效果是与远程仓库同步。
git push <remote> <place>
(如git push origin master
)表示找到本地master分支中的所有提交,向远程仓库origin的master分支中添加其中不存在的提交.<place>
参数指定了要同步的两个分支的位置。
一般的命令是git push <remote> <source>:<destination>
,适用于本地远程分支与关联的远程仓库中的分支不同名的情况。如果<source>
留空,会删除远程仓库的<destination>
分支。
当本地仓库基于过时的远程仓库时
git pull --rebase
相当于git fetch
加上git rebase origin/master
,效果是获取远程仓库的提交记录后,将当前分支的工作转移到最新的远程分支下。
而git pull
相当于git fetch
加上git merge origin/master
,效果与前者一样,不过会引入一次新的合并而非移动当前分支的工作。
参考资料
https://learngitbranching.js.org/
https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1