Git 标准工作流程和 Git 使用(持续更新)
本文介绍一下比较典型的 git 开发流程,从新建一个本地分支开始,到合并到远程主分支。一般的软件项目都会有一个 git 仓库,其中主分支保存着稳定可用的版本,如果想给项目开发新功能,会先从主分支迁出开发分支,在开发分支上进行开发工作。
迁出开发分支前,可以先同步远程仓库
# 1. 切换到主分支
git checkout main# 2. 从远程仓库(origin)拉取最新的 main 分支内容
git pull origin main创建并切换到新的功能分支
# 使用 -b 参数,一步完成“创建”和“切换”两个动作
git checkout -b feature/add-user-profile在这个新分支上,你可以自由地编写代码、修改文件。当你完成一个小的、有意义的功能单元后,就应该进行一次提交(Commit)。
# 1. 查看当前工作区的文件状态
git status# 2. 将你想要提交的所有文件添加到暂存区(. 代表所有已修改和新建的文件)
git add .# 3. 提交暂存区的文件,并附上清晰的提交信息
git commit -m "feat: Add user profile page structure"当你在本地有了一些提交后,应尽快将这个分支推送到远程仓库
# -u 参数会将本地分支与远程分支关联起来
# origin 后面的是要在 origin 上创建的远程分支名
# 第一次推送时使用 -u,之后就可以直接使用 git push
git push -u origin feature/add-user-profile推送分支后,你就可以在远程仓库的网页界面(如 GitHub)上看到一个提示,建议你为刚刚推送的分支创建一个 Pull Request(PR)。PR 的过程中会根据仓库的配置进行 CI/CD,这个检查流程通过后,你的代码就被合并到主分支了。
合并完成后,你的本地还残留着已经完成使命的功能分支。为了保持本地仓库的整洁,你需要做以下清理工作。
# 1. 切换回主分支
git checkout main# 2. 拉取最新的主分支代码(包含了你刚刚合并的变更)
git pull origin main# 3. 删除已经合并的本地功能分支
# -d 会在删除前检查分支是否已被合并,更安全
git branch -d feature/add-user-profile# 如果远程分支没有自动删除,可以用以下命令删除
# git push origin --delete feature/add-user-profile如果在 commit 或者 push 前,远程分支有新的提交怎么办?
虽然我们在创建开发分支前同步了远程分支,但我们开发完成后,远程分支可能有新的改动,此时需要再次进行同步。
你可以通过以下步骤来查看你的分支落后于 main 分支多少。
# 1. 从远程仓库获取最新的数据,但先不合并到你的工作分支
# 这会更新你本地的 "远程分支" 视图(如 origin/main)
git fetch origin# 2. 查看你的当前分支(假设为 feature/add-profile)与 origin/main 的差异
# 这会列出在 origin/main 上有,但在你的分支上没有的提交
git log HEAD..origin/main --oneline# 如果上面命令有输出,就说明 main 分支有你本地没有的更新。
# "HEAD" 指代你当前所在的分支。如果远程分支上真的有更新,要同步这些更新可以 rebase 或者 merge。推荐 rebase,因为他会保持线性的提交记录。rebase 的意思是“重新设置基底”。它会把你当前分支的提交“拎起来”,放到 main 分支最新提交的“顶端”。
# 1. 确保你在自己的功能分支上
git checkout feature/add-profile# 2. 从远程获取最新数据
git fetch origin# 3. 将你的分支 rebase 到最新的 origin/main 上
git rebase origin/mainrebase 过程会发生什么?
- Git 会找到你的分支和
main分支的共同祖先。 - 把你分支上独有的提交暂存起来。
- 将你的分支指针移动到
origin/main的最新位置。 - 最后,把刚才暂存的提交逐一重新应用(replay)到新的位置上。
如果 rebase 过程中出现冲突:
- Git 会暂停
rebase,并提示你哪些文件有冲突。 - 手动解决冲突文件。
- 使用
git add <conflicted-file>标记冲突已解决。 - 执行
git rebase --continue继续rebase过程。 - (如果想放弃此次
rebase,可以执行git rebase --abort)
如果开发过程很长,开发分支落后于主分支很多。那么 rebase 的过程可能比较棘手。(可以在开发过程中定期 rebase,我没有实践过)
如果 PR 没有通过检查怎么办
在 PR 的过程中发现需要在本地再进行一些修改,你可以再修改后重新走 add commit push 这套流程,问题是这样你会创建一个丑陋的“修改commit”。为避免这种没有功能意义的 commit,可以采用两种工具
1. 当你只需要修改最新的一个提交时:git commit --amend
# 1. 将修复后的文件添加到暂存区
git add .# 2. 使用 --amend 来“追加”修改到上一个提交
# --no-edit 表示你不想修改上一次的提交信息
git commit --amend --no-edit2. 当你有多个凌乱的提交需要整理时:git rebase -i (交互式变基)
这个我没用过,有待探索。似乎需要写一个处理历史 commits 的脚本。
无论采用哪种方式,当你修改了已经推送到远程的提交历史后,你本地的分支历史就和远程的不一样了。此时你不能再使用 git push,而必须强制推送。
# --force-with-lease 比 --force 更安全
# 它会检查远程分支在你上次拉取后没有被其他人更新过,才会执行强制推送
git push --force-with-lease origin your-branch-name