Skip to content

Git

提示

一个分布式版本控制系统,用于追踪项目代码的变化。

本地仓库的操作

本地仓库提交

shell
# 本地提交
git commit -m "message"

分支

分支的创建基于``基于某个提交及它的父提交,当前所在的分支会用*`标识

shell
# 创建分支(分支的创建基于某个提交)
git branch ${branch_name}
# 切换到这个分支
git checkout ${branch_name}
# 创建并切换到这个分支
git checkout -b ${branch_name}
# 将source分支指向目标分支或目标版本
git branch -f <source_branch_name> <dest_branch_name|version num>
# 删除指定分支
git branch [-D|-d] <branch_name>

合并

merge

将某个分支A上不被当前分支B包含的提交记录合并到当前分支B上。会在当前分支B下创建一个新的合并记录,此时分支B会包含分支A的所有提交记录。

shell
# 将${branch_name}分支提交记录覆盖到当前分支
git merge ${branch_name}

rebase

相比于mergerebase会从当前分支和目标分支的共同父节点P开始,将当前分支P点后的提交记录都复制到目标分支的最新节点后,最终看起来就像只有一条分支(rebase后的commit id和原来不一致了)。

shell
# 将当前分支合并到${branch_name}上
# git rebase a 会将当前分支的提交记录复制到分支a后面
git rebase [-i] ${branch_name}
# 将child分支的提交记录移到parent的提交记录后
git rebase ${parent_branch} ${child_branch}

HEAD 是一个对当前检出记录的符号引用,指向你正在其基础上进行工作的提交记录。HEAD 总是指向当前分支上最近一次提交记录。

分离HEAD

一般HEAD和分支是一起前进的,通过checkout命令修改HEAD的指针,此时HEAD的状态是detached。又称为detached head,即分离HEAD。

shell
# 会将HEAD指针指向这个commitid或branch
git checkout ${commit_id}/${branch_name}
HEAD -> branch -> commid_a => HEAD -> commit_id & branch -> commit_id

HEAD移动

~^ 都可以移动HEAD的位置,区别在于前者是往上移动几个位置,后者是当前HEAD拥有多个父节点时,HEAD^ 是当前分支的父节点,HEAD ^ 2是另一个父节点。

shell
# 将当前的HEAD向上移动一步,选择第二个父节点,然后再向上移动3步
git checkout HEAD~^2~3

相对引用

shell
# 将HEAD切换到main的父提交记录
git checkout main^
# 将HEAD切换到main的爷提交记录
git checkout main^^
# 向上移动num次
git checkout ~<num>
# 将分支main移动到当前HEAD的相对位置上的第3个提交记录 
git branch -f main ~3

撤销变更

git restore

撤销未提交到本地仓库的改动。

shell
# 回滚所有的改动
git restore .
# 使用checkout也可以实现
git checkout .

git commit --amend

适合提交到本地仓库的改动中错误部分。如果上次提交的改动,有部分改错了,但是不想再多一次提交记录,那么可以使用git commit -m "msg" --amend命令提交当前改动,那么改动会被提交到本地仓库的同时,且只保留提交信息为"msg"的提交记录

git reset

适用本地已提交撤销。通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。原先的修改内容仍然存在,处于未加入暂存区状态

shell
# 将本地分支记录回退一个版本实现撤销
git reset HEAD~1
# 将本地仓库的提交恢复到指定的版本号,--hard表示改动不保留,--soft表示改动保留(默认)
git reset [--hard|--soft] <version num>

git revert

用于撤销远端已提交的更改(会产生回滚记录)。使用git revert命令,在当前提交记录A后多个一个新的提交记录 B,这个新的提交记录B引入了更改(这更改是用来撤销A的更改内容),也就是恢复到提交记录B的父记录状态。

shell
# 撤销更改
git revert HEAD
A -> B => A -> B -> B' (A = B')

cherry-pick

将一些提交记录复制到当前所在位置(HEAD)后。

shell
# 将多个提交复制到HEAD后,按照输入的顺序排序
git cherry-pick <commit_id ...>

相比rebase,更加灵活,可以指定某个分支上的特定几个提交记录,而不是类似git rebase -i的图形化操作界面。

交互的rebase

相比cherry-pick基于提交记录的hash值进行工作,通过--interactive(简写为-i)操作图形化界面。

shell
# 通过图形化界面将当前分支的记录移到${branch_name}后
git rebase -i ${branch_name}

远端仓库的操作

remote tracking

用于指定本地分支对应着哪个远端分支。

shell
# 从远程仓库拉取到本地分支
git checkout -b main o/main
# 将远程仓库拉取到指定分支(不写就是当前分支)
git branch -u o/main main

git fetch

  • 从远程仓库下载本地仓库缺失的提交记录
  • 更新远程分支指针,将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态
shell
# 将从远端分支获取当前分支不存在的提交放到当前分支上
git fetch origin <remote_branch>
# 将从远端分支获取本地分支不存在的提交放到本地分支上
# 如果本地分支不存在,会自动创建
git fetch origin <remote> <local>
# 拉取空的远端分支到本地main分支,其实就是在本地创建一个main分支
git fetch origin :main

git fetch 是单纯的下载操作,不会更新本地仓库的状态,只会将本地的远端分支和远端分支保持同步

git pull

等同于git fetch + git merge, 将远端分支的内容更新到本地,并将本地已存在的修改和更新内容进行merge合并操作。

shell
# 使用fetch + merge
git pull
# 使用 fetch + rebase
git pull --rebase
# 将远端分支拉取到本地分支并执行merge操作
git pull origin <remote> = git fetch origin <remote> + git merge origin/<remote>
git pull origin <remote>:<local> = git fetch origin <remote>:<local> + git merge <local>

git push

shell
# 格式
git push origin <local> <remote>
# 将本地的main分支的内容推送到远端的origin/main分支
git push origin main
# 将本地的foo分支内容推送到远端的main分支
# 可以不是分支,也可以是HEAD位置,只要能够被git识别即可
# 如果远端分支不存在会被自动创建
git push origin foo:main
# 推送空的到远端,会删除远端的main分支
git push origin :main

日常命令

shell
# 设置全局用户名密码
git config --global user.name ${your_name}
git config --global user.email ${your_email}

# 生成公私钥
ssh-keygen -t rsa

# 修改远端分支url
git remote set-url origin ${new_url}

# 修改当前分支名称
git branch -M ${new_branch_name}

# 根据tag拉取代码
git clone -b <tag name> <url>

# 推送tag到远端
git push origin <tag name>

# 删除远端tag标签
git push origin :<tag name>