Git用法总结
Git用法总结
分区
工作区🧱:这是平时编辑代码的地方,也就是的项目文件夹。
暂存区🗃️:当使用 git add 把修改加入暂存区时,Git 会把这些改动标记为准备提交的状态。
本地仓库📦:当运行 git commit 后,改动就会被记录在本地仓库中(也就是 .git 目录下的历史记录)。
远程仓库🌐:通常托管在 GitHub、GitLab、Gitee 等平台上。通过 git push 可以将本地提交同步到远程仓库。
HTTP和SSH
HTTP对应用户名和令牌。令牌通过Settings-Developer Settings-Personal access tokens-Tokens(classic)生成。
SSH对应SSH密钥。密钥通过ED25519或者RSA算法生成都可以。
ED25519:
$ ssh-keygen -t ed25519 -C "my_linux_laptop"
#密钥保存地址,按回车就行
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
RSA:
#生成2048位密钥
$ ssh-keygen -t rsa -b 2048 -C "email@example.com"
#密钥保存地址,按回车就行
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
生成后,以ED25519为例,在主文件夹/.ssh/id_ed25519.pub中复制内容,粘贴在Github-settings-SSH and GPG keys-Authentication keys中。
新建项目
远端新建项目:

从远端拉空项目
命令行
本地通过新建一个库然后SSH关联到远端:
git init
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:hljmssjg/git_blog.git
git push -u origin main
IDE
实战中用Jetbrains的IDE可以通过新建-通过版本控制的项目...直接从远端拉项目,不用输入这些乱七八糟的命令:

从本地推代码到远端空项目(推荐)
命令行
可以将本地现有的代码库ssh推到远端。
git remote add origin git@github.com:hljmssjg/git_blog.git
git branch -M main
git push -u origin main
IDE
实战中用Jetbrains的IDE可以直接通过定义远程、提交并推送:

提交代码
任务描述:完成需求A后使用命令行向远端main分支提交。
命令行:
git pull
git status
git add .
git commit -m "A"
git status
git push origin main
IDE实战:
-
更新项目:

-
将文件添加到git:

- 提交并推送

- 结果:

创建开发分支
任务描述:在当前的main分支上,新建开发分支dev,并开发任务B。
常用命令:
#查看所有分支
git branch
#创建新分支
git branch <branch-name>
#切换分支
git checkout <branch-name>
#创建并切换分支
git checkout -b <branch-name>
实战:
#创建并切换分支
git checkout -b dev
#开发完成后
git status
git add .
git commit -m "Task B"
git status
git push origin dev
实战(IDE):



结果:

Fetch
任务描述:我和同事一起在dev分支上基于B节点进行开发。同事先提交了C,我需要把同事的提交拉下来看看他更新了什么,但不想影响我本地的代码。
# 确保在 dev 分支
git checkout dev
# 从远程同步最新的主分支
git fetch --prune
实战IDE:

这个提取对应的是高级的fetch操作:
git -c credential.helper= -c core.quotepath=false -c log.showSignature=false fetch origin --recurse-submodules=no --progress --prune
结果:

显示有一个传入提交:

Merge
任务描述:我和同事一起在dev分支上基于B节点进行开发。同事先提交了C,我把同事的提交拉下来看了一下,现在想把我的提交D和他的合并:

# 确保在 dev 分支
git checkout dev
# 从远程同步最新的主分支
git fetch --prune
# 合并
git merge origin/dev
手动打开冲突文件,当前头节点HEAD的内容(也就是dev)和远端的origin/dev分支有冲突了。
<<<<<<< HEAD
D
=======
C
>>>>>>> origin/main
这里选择保留dev的内容,把其他的删干净.
把处理好冲突的文件添加到提交区并提交,完成合并操作:
git add .
git commit -m "E"
IDE实战:鼠标右键远程提交,选择将“origin/dev”合并到“dev”中,或者使用“合并”拉入“dev”都可以。

解决冲突:

编辑提交信息为E:

推送到远端:

Pull
git pull = 先git fetch ,再 git merge 或者git rebase
任务描述:我和同事一起在dev分支上基于E节点进行开发。同事先提交了F,我把同事的提交拉下来直接把我的提交G和他的合并。
如果没有冲突,那下列方法将会直接成功:
git checkout dev
git pull

如果有冲突,需要显示指定如何处理冲突:
#用merge
git pull --no-rebase
#用rebase
git pull --rebase
#只快速合并
git pull --ff-only
对于IDE,可以直接使用更新项目:



这段过程等价于:
git -c credential.helper= -c core.quotepath=false -c log.showSignature=false fetch origin --recurse-submodules=no --progress --prune
git -c credential.helper= -c core.quotepath=false -c log.showSignature=false merge origin/dev --no-stat -v
git -c credential.helper= -c core.quotepath=false -c log.showSignature=false add --ignore-errors -A -f --sparse -- main.py
git -c credential.helper= -c core.quotepath=false -c log.showSignature=false commit -F /home/jiangeng/WebstormProjects/git_blog/.git/MERGE_MSG -- [dev 6f5c216] Merge remote-tracking branch 'origin/dev' into dev
结果:

Rebase
git rebase可以压缩提交,也可以合并代码。
压缩提交
命令行
任务描述:当前develop/terminal分支又开发了CM1、CM2、M。使用命令行进行rebase压缩提交,保持提交的干净整洁。

#查看最近的五次提交
git log --oneline -n 5
#压缩最近的三次提交
git rebase -i HEAD~3
pick CM1为基,squashCM2 和M。

写commit:

结果:

注意,如果远程Task CM1、CM2和M都推送过去了,那这个时候直接push会被拒,因为用 git rebase 对本地分支 develop/terminal 进行了“压缩提交”,这就相当于改写了分支的历史。Git 默认不允许把历史被改写的分支强行推送到远程,除非明确表示想覆盖远程的旧历史。
解决办法:
#我知道我改了历史,只要远程分支没有被别人改,我就强推。
git push --force-with-lease

但是这样做,共同开发的队友就需要抛弃掉本地的提交,强行拉一下远程保持一致。
git fetch origin
git checkout develop/terminal
git reset --hard origin/develop/terminal
所以rebase最好是在自己一个人的feature分支里用。
IDE
任务描述:当前develop/IDE分支又开发了CN1、CN2、N。使用命令行进行rebase压缩提交,保持提交的干净整洁。

选中Task CN2和Task N,点击压缩按钮。然后启动变基。

编辑commit内容,推远端时使用强制推送:

结果:

变基分支
任务描述:我和同事一起在dev分支上基于H节点进行开发。同事先提交了I,我把同事的提交拉下来看了一下,现在想把我的提交J和他的合并。

# 确保在 dev 分支
git checkout dev
# 从远程同步最新的主分支
git fetch --prune
# 合并
git rebase origin/dev
IDE实战:


最终推送到远端后结果:

rebase是没有额外的线的,整个git praph简洁美观,但是会更改提交历史。
在实战中,本地feature分支用rebase + squash保持提交整洁。多人协作的 dev、main 等最好用merge。
删除分支
命令行
#删除本地
git branch -d develop/terminal
#删除远端
git push origin --delete develop/terminal
#更新git pragh
git pull
IDE


最终的git graph:

撤销提交
撤销commit
分几种情况:
#commit了还没push,需要撤销提交并保留代码修改
git reset --soft HEAD~1
#commit了还没push,需要撤销提交,同时取消暂存区中代码(但保留代码改动)
git reset --mixed HEAD~1
#commit了还没push,需要撤销提交并清除代码改动
git reset --hard HEAD~1
#改commit内容
git commit --amend
IDE实战:
假设本地有一个useless commit

复制想要回退的commit的修订号:

点击重置HEAD:

将修订号粘贴在为提交这一栏中,设置重置类型(以hard为例)。可以点验证看看是不是那个想要回去的commit:

重置后:

也直接点击提交右键直接操作:

撤销提交对应soft,删除提交对应hard,编辑提交信息对应git commit --amend。
假如已经push到远端了,如果是自己一个人开发的分支,直接git reset 然后强推git push -f就好。
如果是多人协作,最好用revert:
#获取commit的hash
git log --oneline
#revert 对应commit
git revert <commit_hash>
也可以直接右键选择还原提交:

结果:

会在git graph里明确“还原”这个操作,不会改变git history。
撤销merge

#检查log,查看对应的hash值
git log --oneline
#根据hash查看合并的情况
git show 89f5b17

可以看到这是HEAD -> dev fb7222f和origin/dev e48978b的合并。
使用revert选择保留HEAD的提交:
# 对origin/dev做一次反向提交
# 以 第1个 parent 为主干,撤销合并时引入的另一个 parent(e48978b) 的变更
git revert -m 1 89f5b17

或者如果分支只有自己开发,那么选择reset并强推:
#直接回到合并前的状态,抛弃之后的提交
git reset --hard fb7222f
git push -f
IDE只支持简单的撤销操作,对于这种撤销merge的操作要用命令行。
那假如我又反悔了,不想revert“H”,怎么办?可以撤销这次撤销。
撤销rebase
远程先根据G提交了H,本地根据G提交了I,然后rebase到远程H。

如果想要撤回rebase,两种方法:
#使用ORIG_HEAD
git reset --hard ORIG_HEAD
#或者根据git reflog查看:
0dd2433 (HEAD -> dev, origin/dev) HEAD@{8}: rebase (continue): I
9740a81 HEAD@{9}: rebase (start): checkout refs/remotes/origin/dev
bf45968 HEAD@{10}: commit: I
#reset
git reset --hard HEAD@{10}
结果:

总结一句话:创建自己的分支随便瞎折腾。和别人分支合并要慎重。
PR/MR
PR对应github,MR对应gitlab,本质都是合并请求。
开启代码审查
添加经典分支保护规则:



这样设置即使是管理员也无法推送。
本地将dev合并到main后推送到远端:


无论是推送还是强推,都会被拒绝。这里就需要提PR。
提PR
首先确保个人分支已经被推送到远端,然后Github-pull requests-New pull request

选择分支:
- base branch:目标分支(通常是
main或master)。 - compare branch:开发分支(如
dev)。

选择Create Pull request。


然后选择另一个人来审批:

此时审核人的帐号中,可以添加评论:

审核代码,然后批准:

Merge 这个PR:

最终主帐号上会显示PR成功,且会收到邮件提示:
