Git基操

78 阅读5分钟

Git: 多人协作的开源版本管理工具

git的4个核心区域

工作区(Working Directory):

电脑上的工作目录

暂存区(Staging Area):

类似于草稿箱,本质上是一个叫index的二进制文件。{工作目录/.git/index}

本地仓库(Local Repository):

本地的.git目录,包含了项目的所有文件、提交历史、分支、标签等信息。通过git init就能在工作区生成.git目录

远程仓库(Remote Repository):

存储在远程服务器(github/gitlab)上的远程仓库。通过远程仓库,可以共享代码,协同工作

git的三种基本状态

已修改(modified)

工作区的文件已经被修改了,但还未进入暂存区

已暂存(staged)

修改的文件进入了暂存区,等待被提交到本地仓库

已提交(committed)

暂存区的文件已经被提交到本地仓库

git基础

git init		# 初始化工作目录

git status  # 显示当前状态

git add [filename] # add file to staing area

git commit -m "commit"  # 一次提交

git config

配置用户名和邮箱

  1. 可以通过git config命令配置
  2. 可以通过配置config文件,然后保存着本地目录/家目录/系统目录下,对应本地/用户/系统级的config。
  3. 可在config文件中配置添加常用缩略语。
[alias]
    co = checkout
    br = branch
    ci = commit
    st = status

git常用命令

git show  			# 展示上一个commit的详细信息

git log					# 展示当前分支提交历史记录,和对应commit的哈希值
git log --graph # 图形化展示

git diff				# 未暂存(工作区) 和 暂存区 的差异

git diff --cached
git diff --staged # 显示已暂存但未提交的改动

git diff <file>	# 查看指定文件的差异
git diff <commit1> <commit1> # 查看指定的两个commit的差异

git clone [url]				# 下载并关联远程仓库

git remote						# 远程仓库

.gitignore 文件	# 让git不跟踪这些文件 通用模版: https://github.com/github/gitignore

git的分支

git branch <branch-name> # 从当前分支新建一个分支 (未进行切换)  
git checkout <branch-name> # 切换到分支branch-name上  
git checkout -b <branch-name> # 新建并切换到新分支  
git switch <branch>		# 现在用switch单纯进行切换分支  											# checkout既可以用于切换commit(也保留了切换分支的能力)                        
git branch			# 显示本地所有分支 当前分支用*标记  
git branch -r 	# 显示远程所有分支  
git branch -vv  # 显示当前分支关联的远程分支

分支合并 merge vs rebase

git merge

// 在目标分支main上,合入feature分支的代码
git merge branch-feature
  1. 如果无冲突,默认快速合并(fast-forward)。如果分支main是分支feature的子集,git会将当前分支指向feature分支的最新提交。

  2. 如果有冲突(three-way merge),git会创建一个新的提交merge commit,包含两个分支的所有变更内容,我们需要手动解决冲突后提交。

git rebase

git rebase 将当前分支变基到分支branch上.

以target-branch的最新提交为基准,将本分支的提交移动到target-branch的最新提交后。过程中可能有冲突需要解决。

merge的优点是不会修改merge前的历史提交,而rebase或多或少会修改了历史。

merge的缺陷是引入了很多的merge commit,这些commit没有太多的意义,如果想保持工作历史干净推荐用rebase

黄金准则:不要rebase一个共享分支。  例如分支两人公共开发feature分支,最终要合入main分支,对feature分支使用rebase操作会打乱提交历史造成很多混乱。

git rebase创建干净的commit

日常开发中对于开发一个feature我们可能会多次commit,这些commit并非都是有意义的,可能只是加上几个log,修复一些简单的bug...

这时可以用rebase命令创建一个干净的commit

git log			# 查看commit历史记录

git rebase -i <hash-commit> # 以 hash-commit 这条commit 为基准
git rebase -i HEAD~5 # 以前5commit为基准
pick c32e46da 废弃埋点SDK对外暴露的事件分发接口
pick 3ecabc77 Merge: 张梦: 版本号自动升级,从4.12240.0升级到VERSION=4.12240.1
pick fdb100f9 简单功能实现
pick 91431a79 test

-->

pick c32e46da 废弃埋点SDK对外暴露的事件分发接口
squash 3ecabc77 Merge: 张梦: 版本号自动升级,从4.12240.0升级到VERSION=4.12240.1
s fdb100f9 简单功能实现
s 91431a79 test

下一阶段类似,可以修改commit message。即可完成变基操作。

此时再通过git push就能提交一个只包含一个commit的干净的提交了。

如果远程仓库中已经有了这些无意义的commit,可以通过git push -f 将本地的干净的分支强制推送到远程分支。

(注意⚠️禁止对线上分支这样操作)

fetch vs pull

都是从远程抓取代码

git fetch			# 更新本地的远程分支
git pull			# == fetch + merge

有时间并不想直接合入远程的最新提交,因此可以先fetch,再考虑合入这些最新的更改。

git stash

在开发过程中,会遇到开发到一半需要临时切到其他分支的情况,这时git add + git commit 就会产生一条无意义的commit

通过git stash可以暂存当前的修改,然后切换分支去忙别的事。

当切回原来的分支后,通过git stash apply就能恢复原来的代码了

git reset

有时需要一些撤销操作

git reset [file]	# 撤销暂存的文件,但不会撤销更改

git reset <commit>
git reset --soft <commit> # 撤销 commit 后的提交,但本地保留这些修改

git reset --hard <commit> # 撤销 commit 后的提交并清除修改,回到指定commit的状态

一些学习资料

在线学习(闯关)网站

learngitbranching.js.org/?locale=zh_…

一本书  ProGit

www.progit.cn/

一节课

www.bilibili.com/video/BV1Hu…