Git有两个基本作用:
- 版本控制
- 团队开发
一、Git工作流程

二、Git基本配置
设置用户信息
设置:(+如果要查看,只输入双引号前面的就好了)
1 | git config --global user.name "yourname" |
有3种范围:--local只对某个仓库有效,--global对当前用户的所有仓库有效,--system对系统所有登录的用户有效。
要显示config的配置,加--list。
三、Git基本使用
获取本地仓库
git init,执行之后工作目录下就会产生.git隐藏目录。
核心操作
clone(克隆): 从远程仓库中克隆代码到本地仓库checkout(检出):从本地仓库中检出一个仓库分支然后进行修订add(添加): 在提交前先将代码提交到暂存区- 可以接单个文件名,也可以接通配符
commit(提交): 暂存区 –> 本地仓库。本地仓库中保存修改的各个历史版本- 可以接
-m后跟注释
- 可以接
fetch(抓取) : 从远程库,抓取到本地仓库,不进行任何的合并动作,一般操作比较少pull(拉取) : 从远程库拉到本地库,自动进行合并(merge),然后放到到工作区,相当于fetch+mergepush(推送) : 修改完成后,需要和团队成员共享代码时,将代码推送到远程仓库
辅助查看与操作
git status:查看修改的状态git log [option]:查看提交日志,git-log以精简形式查看git log:以默认形式查看提交日志git log --all:显示所有分支的提交日志git log --pretty=oneline:将提交信息显示为一行git log --abbrev-commit:使得输出的 commitId 更简短git log --graph:以图的形式显示提交历史,便于查看分支合并情况
git reflog commitID:记录所有操作,可以回滚到任意地方git reset --hard commitID:版本回退- 添加文件到忽略列表:创建
.gitignore文件,列出要忽略的文件模式
回滚
如果在开发过程中,某个需求不需要了,此时分为3种情况讨论:
- 文件在工作区:执行
git checkout file - 文件在暂存区:执行
git reset HEAD file,让这个文件回到工作区,然后执行1 - 文件在本地仓库:执行
git reset -方式(有3种)hard:工作区、暂存区、本地仓库3个地方保持一致mixed:让文件保存在工作区soft:让文件保存在暂存区
四、Git分支
核心操作
查看本地分支:
git branch创建本地分支:
git branch 分支名切换分支:
git checkout 分支名- 可以直接切换到一个不存在的分支(创建并切换):
git checkout -b 分支名
- 可以直接切换到一个不存在的分支(创建并切换):
合并分支:
git merge 分支名称,一个分支上的提交可以合并到另一个分支删除分支:不能删除当前分支,只能删除其他分支
git branch -d b1删除分支时,需要做各种检查git branch -D b1不做任何检查,强制删除
解决冲突
步骤:
处理文件中冲突的地方
将解决完冲突的文件加入暂存区(
add)提交到仓库(
commit)
GitFlow

master(生产) 分支:线上分支,主分支,中小规模项目作为线上运行的应用对应的分支;develop(开发)分支:是从master创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线要求,都可以在此版本进行开发,阶段开发完成后,需要是合并到master分支,准备上线;feature/xxxx分支:从develop创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完成后合并到develop分支;hotfix/xxxx分支:从master派生的分支,一般作为线上bug修复使用,修复完成后需要合并到master、test、develop分支;还有一些其他分支,在此不再详述,例如
test分支(用于代码测试)、pre分支(预上线分支)等等。
五、Git远程仓库
基本命令
对接远程仓库:
git remote add <远端名称> <仓库路径>查看远程仓库:
git remote推送到远程仓库:
git push [-f] [--set-upstream] [远端名称 [本地分支名]:[远端分支名]]- 如果远程分支名和本地分支名称相同,则可以只写本地分支
git push origin master -f表示强制覆盖--set-upstream推送到远端的同时并且建立起和远端分支的关联关系- 如果当前分支已经和远端分支关联,则可以省略分支名和远端名
- 如果远程分支名和本地分支名称相同,则可以只写本地分支
查看本地分支与远程分支的关联关系:
git branch -vv从远程仓库克隆:
git clone <仓库路径> [本地目录]从远程仓库抓取/拉取:(如果不指定远端名称和分支名,就抓取所有分支)
git fetch [remote name] [branch name]:将仓库里的更新都抓取到本地,不进行合并。git pull [remote name] [branch name]:将远端仓库的修改拉到本地并自动进行合并,等同于fetch+merge
解决冲突
远程分支也是分支,解决冲突的方式和本地相同(看上文)。
需要先拉取远程仓库的提交,经过合并后才能推送到远端分支:

六、进阶命令
交互式变基
在本地使用,重新排序、合并、拆分、编辑或删除提交,从而整理提交历史,使其更加清晰。
rebase和merge的区别:都是实现合并分支,但是细节不同,rebase会把复杂的提交历史修订为干净整洁的线性结构,并且产生新的commitID。

使用步骤:
执行
git rebase -i HEAD~5,此时打开一个编辑器,显示最近的5个提交,每个提交前有一个命令(默认是pick)编辑提交列表,修改每一行前面的命令,例如
pick改成rewordGit会按照指令提交
常用命令:
| 命令 | 缩写 | 作用 |
|---|---|---|
pick |
p |
保留该提交(不做修改) |
reword |
r |
修改提交信息 |
edit |
e |
暂停 rebase,允许修改提交内容(如增删文件)或提交信息 |
squash |
s |
合并到前一个提交,并保留提交信息 |
fixup |
f |
合并到前一个提交,但丢弃当前提交的提交信息 |
drop |
d |
删除该提交 |
exec |
x |
执行一个 shell 命令(如运行测试) |
注意事项:
不要修改已经推送到远程仓库的提交历史(除非确定没有其他人基于此工作)
如果遇到冲突:
- 解决冲突后,用
git add标记为已解决 - 继续 rebase:
git rebase --continue - 或终止 rebase:
git rebase --abort - 解决后强制推送到远程:
git push --force
- 解决冲突后,用
储藏
临时保存未提交的更改,将当前工作目录和暂存区的修改保存到一个“储藏区”(stash stack),可以快速切换分支或处理其他任务,后续再恢复这些更改。
基本命令:
| 基本命令 | 具体操作 | 说明 |
|---|---|---|
| 存(入栈) | stash (push) |
默认存入当前工作区的修改到栈中 |
stash save "注释" |
可以连续存多次变动代码,添加注释方便区分 | |
| 取(出栈) | stash pop |
取出栈顶的修改并应用到当前工作区,同时从栈中移除该修改 |
注意:确保此时 pop 的变动代码是你需要的,否则 pop 后可能需要重新压栈 |
||
stash apply |
取出栈顶的修改并应用到当前工作区,但不从栈中移除该修改(类似 peek) |
|
| 清除 | stash drop |
丢弃栈顶的修改 |
stash clear |
清空整个 stash 栈 | |
| 查看 | stash list |
查看 stash 栈中的所有修改记录 |
stash show + 栈索引 |
查看指定索引位置的修改详情 |
使用场景:
- 切换分支时,当前分支有未完成的代码。
- 需要紧急修复其他分支的 Bug,但不想提交当前代码。
- 临时保存实验性代码,避免污染提交历史。
- 合并冲突前,先保存当前改动。
使用示例:
1 | 1. 当前有未提交的修改,但需要切换到其他分支 |
挑选
工作在多分支结构的提交维度上,与merge的区别:
merge:需要另一个分支上的所有变动cherry-pick:需要另一个分支上的部分变动
提交情形:

当产生冲突时,会停下来让用户决定,此时有3种情况:
--continue:解决冲突后,git add,再执行此命令继续合并--abort:放弃合并,回到之前的状态--quit:放弃合并,且不回到之前
比较不同
diff命令,主要讲解两点提交和三点提交的区别:

七、铁令
切换分支前先提交本地的修改
代码及时提交,提交过了就不会丢
遇到任何问题都不要删除文件目录
tag与go modules
Git 和 Go Modules 的一个重要机制:Tag(标签)是打在具体的 Commit(提交)上的,而不是打在分支上的。
只要你的那个 Commit (e9680046ed2f) 存在于远程仓库中(无论它是在 feature 分支、develop 分支,还是悬空的),只要你给它打上了 v1.3.21 的标签并推送到远程,Go 就能引用到它。
具体操作流程
你只需要确保针对那个 Commit 打了标签并推送即可:
1. 在 go-idt 仓库操作
你甚至不需要切换分支,直接指定 Commit ID 打标签即可:
1 | # 直接给指定的 commit hash 打标签 (无论它在哪个分支) |
2. 在引用方(你的主项目)操作
1 | # 修改 go.mod 中的 replace 为 v1.3.21 |
为什么这样做是可以的?
Go 的依赖管理工具(go mod)在拉取代码时,逻辑是这样的:
- 去找
code.sangfor.org/.../go-idt.git这个仓库。 - 询问仓库:“有没有一个叫
v1.3.21的标签?” - 仓库回答:“有,这个标签指向 Commit
e9680046ed2f。” - Go 下载那个 Commit 的代码。
它完全不关心这个 Commit 是属于 master 分支还是某个临时的开发分支。
只有一个小注意事项
虽然技术上不需要合并到 master,但在管理上建议注意:
如果你的 v1.3.21 是基于一个临时分支打的,以后这个分支被删除了,或者这个 Commit 永远没合入主线,可能会导致代码历史比较混乱(虽然 Tag 依然存在,代码不会丢,但在 git log 的树形图里看会比较孤立)。
修改分支的base:onto
git rebase --onto 是 Git 中最强大的命令之一,你可以把它理解为 “精准的外科手术式移植”。
普通的 git rebase master 只能处理简单的“把当前分支基底换到 master”的情况。而 --onto 允许你截取某一段特定的提交记录,嫁接到另一个地方去。
它主要用于解决 “链式分支依赖”(Branch Chaining)的问题。
核心语法
1 | git rebase --onto <移植到的目标位置> <被剪切的起始位置(不包含)> <要移动的分支> |
也就是:
git rebase –onto
最经典的场景:孙子分支“借尸还魂”
假设你有以下分支结构:
- master: 主干。
- feat-A: 基于 master 开发的功能 A。
- feat-B: 基于 feat-A 开发的功能 B(因为 B 依赖 A 的代码)。
现在,feat-A 因为某些原因被废弃了(或者已经合并进 master 了,或者你想把 feat-B 独立出来),你需要把 feat-B 单独移到 master 上,并且不要 feat-A 的那些提交。
1. 现状图示
Plaintext
1 | A --- B (master) |
如果你直接在 feat-B 上执行 git rebase master,Git 默认会沿着线往回找,把 C, D, E, F 全部拿过来。这通常不是你想要的,你不想要 C 和 D。
2. 目标图示
你想达到的效果是把 E 和 F 摘出来,直接接在 B 后面:
Plaintext
1 | A --- B (master) |
(注意:C 和 D 依然在 feat-A 上,但 feat-B 已经和它们没关系了)
3. 使用 git rebase --onto
你需要告诉 Git 三件事:
- 嫁接到哪?
master - 从哪剪断?
feat-A(意思是从 feat-A 之后开始算) - 移动谁?
feat-B
命令如下:
Bash
1 | git rebase --onto master feat-A feat-B |
翻译成人话就是:
“请把
feat-B分支上,排除掉feat-A里的那些提交,剩下的部分(也就是 E 和 F),移植到master上去。”
另一个常用场景:删除中间的一段提交
虽然可以用 git rebase -i (交互式) 来做,但 --onto 也可以用来快速剔除一段提交。
假设你的提交历史是:
base — commit1 — commit2(坏的) — commit3(坏的) — commit4(好的) — HEAD
你想删掉 commit2 和 commit3,直接让 commit4 接在 commit1 后面。
Bash
1 | # 这里的 base 指的是 commit1 的哈希值 |
这会将 commit3 之后 的所有提交(也就是 commit4),嫁接到 commit1 上。
总结与记忆法
记住这三个参数的位置:
1 | git rebase --onto 目的地 剪切点(不含) 当前分支 |
- 参数 1 (Target): 地基。新的树根。
- 参数 2 (Upstream): 以前的旧树根(你想从哪里把树枝砍断)。Git 会忽略这个点以及它之前的所有 commit。
- 参数 3 (Branch): 树枝的顶端。
风险提示
执行这个命令后,可能会遇到**冲突 (Conflict)**。因为你跳过了中间的某些提交(比如上面例子中的 C 和 D),如果 E 和 F 依赖于 C 或 D 修改过的代码,Git 就不知道该怎么合并了,这时你需要手动解决冲突。
使用举例
之前在local开发分支,这个分支大家都在往里合代码,然后我现在的代码一直在rebase这个开发分支,但是后来计划有变,需要从开发分支的某个提交拉取一个新的开发分支,然后我的代码需要合并到这个新的开发分支上:
1 git rebase --onto origin/develop-<新开发分支> origin/develop-<老开发分支> <特性分支名>
仓库推送
标准流程就是:先提交代码入库,再执行命令发布。
为了保证公司内部引用的版本规范和安全,建议你严格按照以下 4 个步骤操作:
1. 修改版本号 (Version Bump)
在提交代码前,非常重要的一步是修改版本号。
通常是在 setup.py、pyproject.toml 或 init.py 里。
- 比如把
1.0.1改成1.0.2。 - 原因:如果不改版本号,同事的 pip 可能会认为没有更新,拉不到你的新代码。
2. 提交代码 (Git Commit & Push)
把修改后的代码(包含新的版本号)推送到 Git 仓库。
1 | git add . |
- 这一步是为了存档,确保“代码库”里有这份代码。
3. 打包构建 (Build)
通常你需要把源码打包成 Python 的安装包(.whl 或 .tar.gz)。
在项目根目录下执行(示例):
1 | python setup.py sdist bdist_wheel |
执行完后,你的 dist/ 目录下会生成类似 my-library-1.0.2.tar.gz 或 my_library-1.0.2-py3-none-any.whl 的文件。
4. 上传发布 (Rsync)
最后一步,才是用那个 rsync 命令,把刚才打好的包,传到公司的私有源服务器上。
总结
顺序不能乱:
- 改版本号 (否则发了也是白发)
- Git Push (保存源码)
- Build (生成安装包)
- Rsync (上架给别人用)