Git之基本用法(2)
在Git基本用法中,我们介绍了工作区,暂存区,版本库等概念,并介绍了本地git仓库中文件的各种状态,以及添加修改、创建提交以及相关的撤回的命令。接下来我们将继续介绍git的基本用法
git branch
分支是Git中的一个重要概念,实际研发流程就是紧密依赖不同分支实现的。分支本质上是指向一系列提交的指针。它允许你从开发主线分离出来,在不影响主分支的情况下进行独立的开发工作。
分支改名
我们在本地git init
创建了一个本地仓库后,默认的主分支名是master。而为了避免敏感词汇,如今我们更推荐将主分支命名为main,因此我们可以使用命令git branch -M
对当前分支进行改名:
1 | git branch -M main |
创建分支
有两种创建分支的方式:
- 使用
git branch <branch-name>
命令可以以当前分支为起点,创建一个分支 - 使用
git checkout -b <branch-name>
可以以当前分支为起点,创建并跳转到新的分支
这里以创建分支feat/feat1
为例:
1 | git branch feat/feat1 |
跳转分支
使用git switch <branch>
或git checkout <branch>
命令实现分支跳转
临时保存分支修改
如果目前在当前分支上已经有了一些未提交的修改,这时有一个紧急的 bug 需要在 main 分支上修复,就必须将当前修改进行保存
使用 git stash
命令将修改保存到 stash 栈:
1 | git stash |
这会将工作目录和暂存区的修改保存起来,并将工作目录和暂存区恢复到最近一次提交的状态。
使用 git stash list
命令查看 stash 栈中的内容:
1 | git stash list |
它会列出所有存储在 stash 栈中的修改,每个存储都有一个唯一的标识符,如 stash@{0}
、stash@{1}
等。
使用 git stash apply
命令将最近一次存储的修改应用到当前工作目录:
1 | git stash apply |
如果你想应用特定的 stash 项,可以使用 git stash apply stash@{n}
,其中 n
是 stash 项的索引。
应用 stash 时,修改会被应用到工作目录,但不会从 stash 栈中删除。如果要同时删除 stash 项,可以使用 git stash pop
:
1 | git stash pop |
它会将最近一次存储的修改应用到工作目录并从 stash 栈中删除。
可以使用 git stash save "message"
命令为 stash 保存添加描述信息,以便更好地识别 stash 中的内容:
1 | git stash save "Working on new feature, not completed yet" |
使用 git stash clear
命令可以清空 stash 栈中的所有存储:
1 | git stash clear |
合并分支
合并分支也有两种方式:
git merge
会创建一个新的合并提交,将两个分支的修改合并在一起git rebase
会将一个分支上的提交移到另一个分支的末尾,让提交历史看起来是线性的。
比如我们在feat/feat1
上有了新的提交之后,就可以尝试将该分支与主分支main合并:
git merge:
1 | (main)$ git merge feat/feat1 |
或git rebase:
1 | (feat/feat1)$ git rebase main |
如果两个分支对同一文件有不同的修改,就会产生冲突,这时就需要手动解决冲突后git add .
提交修复后的内容,再使用git merge --continue
或git rebase --continue
,或者使用--abort
放弃合并
Git中合并分支的方式主要有两种:Fast-forward合并和Three Way Merge合并:
- Fast-forward:当试图将一个分支合并到另一个分支时,如果要合并的分支(源分支)是当前分支(目标分支)的直接后继,即要合并的分支是从当前分支直接分出去的,并且在源分支创建之后,当前分支没有新的提交,那么 Git 会使用 fast-forward 合并,即Git 会直接将源分支的指针向前移动(快进)到目标分支的最新提交
- Three Way Merge:当试图将一个分支合并到另一个分支时,要合并的分支(源分支)是从当前分支(目标分支)直接分出去的,并且在源分支创建之后,当前分支有新的提交,那么Git会使用three-way-merge合并:如果两个分支见存在冲突,需要先解决冲突并将修改加入暂存区,然后进行合并后git会提交一个**合并提交(merge commit)**,而这个合并提交有两个父提交,分别来自合并的两个分支,详情可见git之.git目录详解中object的介绍。最新版本中git使用Ort策略实现Three Way Merge。
git tag
Git 中的 tag 是一个指向某个特定提交的引用,通常用于标记项目中的重要版本或里程碑。它类似于一个分支,但不同的是,分支可以随着新的提交而移动,而 tag 是一个静态的指针,它会一直指向特定的提交,不会随着新的提交而改变。
git tag又分为轻量级tag和附注tag,前者只是一个指向提交的指针,不包含额外的信息,后者包含更多信息,如创建者、创建日期、标签信息等。
1 | # 轻量级 |
附注标签还会对应一个tag object(轻量级标签没有),详情见git之.git目录详解中对object的介绍
git remote
绑定远程仓库
通过git remote add
命令绑定远程仓库,如
1 | git remote add origin https://github.com/DopamineNone/testGit.git |
其中origin
是指远程仓库的默认名称。
查看绑定的远程仓库
使用git remote -v
可以查看:
1 | $ git remote -v |
这与.git/config
文件中记录的一致:
1 | [remote "origin"] |
设置不同的push和fetch url
git remote set-url --push <name> <newurl>
可以单独设置push url
1 | $ git remote set-url --push origin https://DopamineNone/testGithubFlow.git |
该设置常用于fork仓库中:即本地仓库与源开源仓库同步(fetch),推送时讲本地提交更新至远程fork仓库(push)
推送本地提交信息
前文中只标识了远程仓库的地址的默认别名origin
,如将本地提交推送至远程空仓库时,还需要绑定分对应的upstream
1 | git push -u origin main |
这一步就是将本地main
分支的upstream设置为orign/main
(-u选项的作用),并执行推送。(但仍然不会设置其他分支的upstream)
也可以主动修改本地分支的upstream:
1 | git branch --set-upstream-to=origin/feature feature |
就是将feature
分支的upstream设置为origin/feature
。
如果当前分支feat1
没有设置upstream,但main分支设置了,可以直接使用git push origin feat1
,这会将feat1
推送至origin/feat1
(但仍然不会设置feat1
的upstream)
如果当前分支feat2
的upstream已经设置为origin,那么就可以直接执行git push
,等价于`git push origin feat2
获取远程仓库最新提交信息
前提是本地main分支设置了upstream
git fetch <repository> <branch>
命令可以获取远程仓库相应分支的最新提交信息
不指明repository和branch时,等效于
git fetch origin 与当前本地分支同名的远端分支
获取远程仓库最新提交信息后还需要git merge
合并一下。
或者使用git pull <repository> <branch>
命令,等价于git fetch <repository> <branch>
+git merge
如果当前分支feat
已经设置了upstream为orign/feat
,那么git pull
等价于git pull origin feat
分支管理工作流
有了上述的基础,我们就可以了解实际研发中的分支管理。常见的分支管理流有:Git Flow,Github Flow以及Gitlab Flow。推荐阮一峰大佬的博文:Git 工作流程,本文就不赘述相关内容。