0%

Git收集

在写给同在美国的好友刘晓阳的信里,王小波说:“我们背井离乡,到这儿来无非为了名利二字。既然为名为利,就说不上清高。既然不清高,就不配要面子。豁出面皮来撞就是了。”

Git入门

一、基础

  1. 介绍:Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。它是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。
  2. 安装git
    • Linux
      • 命令行安装
      • 源码编译安装
    • Mac OS
      • 通过homebrew安装
      • 通过xcode安装
    • Windows
      • 下载可安装文件直接安装
  3. 基本原理
    • git数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名
    • git是把数据看作是对小型文件系统的一组快照,每次你提交更新在git中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引
    • git用以计算校验和的机制叫做SHA-1散列(hash,哈希)。这是一个由40个十六进制字符(0-9和a-f)组成字符串,基于git中文件的内容或目录结构计算出来。
    • git有三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。
      • 已提交表示数据已经安全的保存在本地数据库中
      • 已修改表示修改了文件,但还没保存到数据库中
      • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中
    • git项目的三个工作区域的概念:git仓库、工作目录以及暂存区域
      • git仓库目录是git用来保存项目的元数据和对象数据库的地方。这是git中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据
      • 工作目录是对项目的某个版本独立提取出来的内容。这些从git仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改
      • 暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在git仓库目录中,有时候也被称作’索引’
    • 基本的git工作流程如下:
      • 在工作目录中修改文件
      • 暂存文件,将文件的快照放入暂存区域
      • 提交更新,找到暂存区域的文件,将快照永久性存储到 git 仓库目录

二、常用操作

所有的命令都可以查看手册,如:git init –help,以下只是常用的一些命令整理

  1. git init

  2. git config –global user.name xxxx

  3. git config –global user.email xxxx@qq.com

    • –global 参数可选,带此参数则配置全局有效,不带则只有此仓库生效
  4. git add filename 添加文件到到暂存区

    • 开始跟踪新文件
    • 把已跟踪的文件放到暂存区
    • 合并时把有冲突的文件标记为已解决状态
  5. git commit 的使用

    • git commit -m ‘comment’ 推送暂存区修改并添加描述
    • git commit -a -m ‘comment’ 推送工作区修改并添加描述
    • git commit –amend -m 推送暂存区修改,覆盖上一次推送并添加描述
  6. git pull origin branch_name 拉取远程最新代码

  7. git push 的使用

    • git push branch_name 推送本地代码到远程
    • git push –delete branch_name 删除远程分支
      • 如:git push origin –delete v1.1.0
  8. git checkout 的使用

    • git checkout dev 切换分支(一是使 HEAD 指回 dev 分支,二是将工作目录恢复成 dev 分支所指向的快照内容)
    • git checkout -b [branchname] [tagname] 在特定的标签上创建一个新分支
    • git checkout – filename 撤销未添加到暂存区的修改
  9. git reset 的使用

    • git reset –hard commit_id 回滚指定提交的版本
    • git reset HEAD filename 撤销已添加到暂存区的修改
  10. git diff 的使用

    • git diff 当前做的哪些更新还没有暂存(只显示尚未暂存的改动)
    • git diff –cached 有哪些更新已经暂存起来准备好了下次提交
  11. git tag 的使用

    • git tag 列出已有标签
    • git tag tag_name 轻量标签
    • git tag -a tag_name -m ‘comment’ 打附注标签
    • git tab -a tag_name -m ‘comment’ commit_id 对某个提交打附注标签
  12. git show tag_name 查看标签相关信息

  13. git config –global http.proxy http://127.0.0.1:7890,设置代理

    • git config –global unset http.proxy
  14. git branch -M main,将当前分支重命名为main

  15. 查看某个文件修改记录git log -- filename或git log --pretty=oneline filename

  16. 查看某个作者修改记录git log --author=author或git log --author=author --pretty=oneline

  17. 查看每次修改的文件列表及文件修改的统计git log --stat或git whatchanged --stat

  18. 每次修改的文件列表并显示状态git log --name-status

  19. 每次修改的文件列表git log --name-only

  20. 查看某次提交git show commit_id

  21. 删除本地分支git branch -d branch_name

  22. 查看远程分支git branch -r

  23. 删除远程分支git push origin --delete branch_name

  24. 撤销add文件git reset HEAD filename或git reset HEAD .

  25. 对比两个分支的差异

    • git diff branch1 branch2 –stat //显示出所有有差异的文件列表
    • git diff branch1 branch2 文件名(带路径) //显示指定文件的详细差异
    • git diff branch1 branch2 //显示出所有有差异的文件的详细差异
  26. git log中文文件名乱码,git config --global core.quotepath false

  27. git push时不用每次都输入用户名和密码:git config --global credential.helper store

  28. git config --unset user.name或全局git config --global --unset user.name

  29. Your account has been blocked,导致这个问题的原因有很多,接解决方案也就不同,我是第二种情况:

    • 方案一:重新设置远程仓库git remote set-url origin 远程仓库地址
    • 方案二:ssh模式下重新生成ssh-keygen -t rsa,并将id_rsa.pub生成的内容粘贴到gitlab后台
  30. 清除untracked files

    • 文件:git clean -nf
    • 目录:git clean -nfd
    • -n参数可用来查看删掉哪些文件
  31. 忽略已加入仓库的某个文件、文件夹

    • 修改本地仓库下的.gitignore文件,将要忽略的文件、文件夹加入
    • 执行命名git rm -r --cached file/dir
    • git push
  32. 使用脚本进行统计git log --author="liuyulong" --pretty=tformat: --since=2018-01-01 --until=2018-12-31 --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

  33. 忽略权限

    • git config core.filemode false git中加入忽略当前版本库文件权限的配置
    • git config --global core.fileMode false git中加入忽略所有版本库文件权限的配置
  34. 移除文件夹

1
2
3
git rm -r --cached folder
git commit -m 'remove folder'
git push
  1. 解决git push 中remote: Permission to xxxxx.git denied to xxx. fatal: unable to access ‘https://github.com/ xxxxx.git/‘: The requested URL returned error: 403。
1
2
3
4
5
6
7
8
9
10
11
12
13
#修改.git/cofig中的url
cd project
vim .git/config
将[remote "origin"]
url = https://github.com/git的用户名/仓库名称.git
修改为
url = https://git的用户名@github.com/git的用户名/仓库名称.git

#或者直接使用命令行:
git config remote.origin.url https://git的用户名@github.com/git的用户名/仓库名称.git

#重新推一下
git push -u origin master
  1. 查看信息

    • git log [<options>] [<revision range>] [[--] <path>...]
    • git show [<options>] [<object>...]
  2. 将本地代码推送至github

    • git init
    • touch .gitignore,添加忽略文件
    • git add .
    • git commit -m ‘提交代码注释’
    • 去github创建仓库,假设仓库名叫study
    • git remote add origin https://github.com/你的github账户/study
    • git pull origin master –allow-unrelated-histories
    • git push -u origin master【需要输入github账号密码】
  3. 远程创建好分支并同步到本地

    • gitlab后台已创建好开发分支,如v5.5.5
    • 打开项目目录 code .
    • 创建并切换到本地分支 git checkout -b v5.5.5
    • git branch –set-upstream-to=origin/v5.5.5 v5.5.5
  1. 本地有修改,远程也修改了,且本地修改早于远程
  • git fetch –all
  • git reset –hard orgin/master
  • git pull
  1. 删除本地/远程分支

    • git branch -d feature/100
    • git push origin -d feature/100
  2. 忽略大小写:git config core.ignorecase true


将本地代码托管到github

  1. 注册github账号、配置SSH-KEY、添加仓库repo等略过
  2. git remote 的使用
    • git remote -v 查看已经配置的远程仓库
    • git remote add 添加一个远程仓库并指定一个简写
  3. git fetch branch_name 从远程仓库中获得数据(不合并或修改当前的工作)
  4. git pull branch_name 从远程仓库中抓取数据并合并到当前所在的分支
  5. git push 的使用
    • git push tagname 推送指定标签到远程仓库
    • git push branch_name 推送分支到远程仓库
    • git push -u branch_name 第一次推送分支到远程仓库
  6. git remote show 查看远程仓库
  7. git remote rename old_name new_name 远程仓库的重命名
  8. git remote rm 远程仓库的重命名
  9. git config –global alias.别名 命令名 全局重命名命令
  10. git branch –set-upstream-to=origin/remote_branch local_branch 本地关联远程分支

一台电脑配置两个github账户

  1. 背景交代:很早的时候用QQ邮箱注册了一个github账户,零零散散的写了一些东西,给人的感觉很不正式(找过工作的人都应该懂得),后来就用手机邮箱注又一个。那么问题来了,想同时在两个账号工作互不影响,手里就一台笔记本怎么办?如果你也有这样的问题那就看一下这篇文章吧。

  2. 准备工作:台式机OR笔记本一台,装好git,熟悉一些基本的git命令

  3. 撸起袖子开干

    • 生成两对秘钥放到C:\Users\Administrator.ssh目录下
      • 秘钥一
        • 输入命令ssh-keygen -t rsa -C “123456@qq.com“
        • 在第一个提示后输入:id_rsa_one(如果默认第二次生成的会把第一次的覆盖掉)
        • 一路回车完事儿
      • 秘钥二
        • 输入命令ssh-keygen -t rsa -C “188****8888@163.com”
        • 在第一个提示后输入:id_rsa_two(分跟第一次生成的区分开)
        • 一路回车完事儿
    • 登录123456@qq.com的github账号,找到SSH and GPGkeys选项,点击New SSH key按钮,编辑打开id_rsa_one.pub,复制里面的内容粘贴到富文本框,随便起个名字然后保存
    • 登录188****8888@163.com的github账号,找到SSH and GPGkeys选项,点击New SSH key按钮,编辑打开id_rsa_two.pub,复制里面的内容粘贴到富文本框,随便起个名字然后保存
    • (可选)ssh-agent bash
    • (可选)ssh-add -l 如果为空就添加
    • 在C:\Users\Administrator.ssh目录下创建config文件,添加以下内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Host abc.com(名字随便起)                 
    HostName github.com(github账号必须得填github)
    IdentityFile C:\Users\Administrator\.ssh\id_rsa_one
    PreferredAuthentications publickey
    User abc

    Host xyz.com(名字随便起)
    HostName github.com(github账号必须得填github)
    IdentityFile C:\Users\Administrator\.ssh\id_rsa_two
    PreferredAuthentications publickey
    User xyz
    • 测试下配置成功了木,分别输入以下命令,如果成功了会有提示信息

      1
      2
      ssh -T git@abc.com 
      ssh -T git@xyz.com
    • 设置一个全局git账号

      1
      2
      git config --global user.name one
      git config --global user.email 123456@qq.com
    • 在github账号123456@qq.com下新建一个仓库test

    • 克隆到本地

      1
      2
      3
      4
      5
      原先的写法:
      git clone git@github.com:your_name/test.git

      现在的写法:
      git clone git@abc.com
    • 进入目录并设置git账号密码(非全局)

      1
      2
      git config user.name two
      git config user.email 188****8888@163.com
    • 正常编辑然后推送,登入github账号123456@qq.com,查看推送信息即可看到

  1. 问题:本地电脑配了好几个github、gitlab、gitee账号,同时也生成了好几对公私钥,当时配完了就不管了。后来突然有一天,本地码完代码之后推送到远程的时候不管用了(github上的私有仓库),一直提示Repository not found,BZ以为是本地仓库账号配错了,折腾了好久都不起作用。后来想到可能是哪个地方配错了,最终还真是这,再次记录下。
    • git push报错Repository not found
    • ssh -T git@github.com,账号明明对着了,就是提示git@github.com: Permission denied (publickey).
    • ssh -T git@liusir.me,即上面第七步,Hi liusirdotme! You've successfully authenticated, but GitHub does not provide shell access.
    • git remote add origin git@liusir.me:liusirdotme/liusirdotme.git
    • git push -u origin master

记一次代码合并的错误

  1. 合并流程:开发分支develop合并到功能分支,功能分支合并到仿真分支,仿真分支合并到master
  2. 假设:
分支名称 最后一次正确提交ID 说明
master aaaaaaaa
fangzhe bbbbbbbb
develop cccccccc 罪魁祸首
v1.x.x dddddddd
  1. 处理步骤:
    • git reset –hard dddddddd && git push –force
    • git reset –hard bbbbbbbb && git push –force
    • git reset –hard aaaaaaaa && git push –force
    • 再分别把 v1.x.x 分别合到 fangzhen、master 上,其余正常操作就完事
  1. 感悟:
    • 生产环境数据处理首要考虑数据量,内存溢出,处理数据进度
    • git怎么提交、合并代码才能不出错
    • git代码合并错误回滚的步骤、常用操作命令

暂存

  1. 添加暂存git stash [--args]
    • 暂存未跟踪或忽略的文件 :-u/–include-untracked
    • 可以stash当前目录下的所有修改:-a/–all
  2. 重新应用暂存并删除原有暂存 git stash pop
  3. 重新应用暂存并保留原有暂存 git stash apply
  4. 查看暂存 git stash list
  5. 删除指定暂存 git stash drop stash@{0,1…n}
    • 删除所有暂存 git stash clear
  6. 基于暂存创建分支 git stash branch new_branch

删除本地分支并推送到远程

  1. 方式一
  • git branch -d branch_name
  • git push origin :branch_name
  1. 方式二
  • git branch -r -d origin/branch_name
  • git push origin :branch_name
  • git branch -D branch_name
  1. 方式三
  • git push origin –delete branch_name
  • git branch -d branch_name

扩展

  • git branch -a 查看本地和分支
  • git branch -r 查看远程分支
  • git branch -d branch_name 删除本地已merge的分支
  • git branch -D branch_name 删除本地分支(包含未merge)

Git只合并某几次提交

  1. cd ~

  2. git init git_cherry

  3. cd git_cherry

  4. vim master.txt

    1
    This is master file
  5. git add .

  6. git commit -m ‘master first commit’

  7. git checkout -b develop

  8. vim master.txt,增加以下内容

    1
    This edtion is in develop branch
  9. git add .

  10. git commit -m ‘in develop branch edit master.txt’

  11. vim develop.txt

    1
    This is develop file
  12. git add .

  13. git commit -m ‘init develop.txt and commit’

  14. git log,拿到需要合并的提交id

  15. git checkout master

  16. git cherry-pick commit_id

  17. git log


git修改remote origin

  1. 直接修改git remote set-url origin url

  2. 先删后加git remote rm origin && git remote add origin url

  3. 直接修改config文件

  4. 使用客户端修改如SourceTree

    博主本地有多个公私钥对:

    1
    2
    config           id_rsa.pub       id_rsa_dotme.pub
    id_rsa id_rsa_dotme known_hosts

    vim config

    1
    2
    3
    4
    5
    Host liusir.me
    HostName github.com
    IdentityFile /Users/your_name/.ssh/id_rsa_dotme
    PreferredAuthentications publickey
    User abc

    修改remote origin

    1
    2
    3
    4
    5
    git@github.com:liusirdotme/liusirdotme.git

    改为

    git@liusir.me:liusirdotme/liusirdotme.git
  5. Git官网


command not found:gitk

  1. 查看git版本 git --version //git version 2.20.1 (Apple Git-117)
  2. 更新brew库 brew update
  3. 重新安装git brew install git
  4. 关闭重新打开 gitk,打完收工

gitk模糊问题

  1. 关闭rootless,重启mac,command+r,选择终端,输入csrutil disable
  • 查看rootless状态 csrutil status
  • 开启rootless csrutil enable –without debug
  1. 修改Wish.app的Info.plist
  • 切换目录 cd /System/Library/Frameworks/Tk.framework/Versions/Current/Resources
  • 编辑Info.plist sudo gedit ./Wish.app/Contents/Info.plist
  • 加入以下代码 <key>NSHighResolutionCapable</key> <true/>
  1. 更新Wish.app sudo touch Wish.app
  2. 设置完毕后重新打开rootless csrutil enable
  3. 参考

本地新建分支并推到远程

  1. 方式一

    1
    2
    3
    4
    5
    6
    7
    1.切换到master分支:git checkout master 
    2.拉取最新代码:git pull
    3.基于master创建featur_branch分支:git checkout -b feature_branch
    4.将本地分支关联到远程分支:git push origin feature_branch:feature_branch
    5.git branch --set-upstream-to=origin/remote_branch(名字自定义) feature_branch(刚建那分支名称)
    步骤4、5可换成以下命令:
    * git push --set-upstream origin feature_branch
  2. 方式二

    1
    2
    git checkout -b v1.1.0_bugfix
    git push --set-upstream origin v1.1.0_bugfix

git push报错:remote: Password authentication is temporarily disabled as part of a brownout

  1. git push报错

    1
    2
    3
    remote: Password authentication is temporarily disabled as part of a brownout. Please use a personal access token    instead.
    remote: Please see https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations/ for more information.
    fatal: unable to access 'https://github.com/liusirdotme/liusirdotme.git/': The requested URL returned error: 403
  2. 点击报错信息提供的url,可看到大概意思是加强了安全验证之类的

  3. 根据指引,先去创建access_token,复制,等下要用

  4. 创建完后根据指引去设置本地仓库

  • 验证是否安装osxkeychain helper,git credential-osxkeychain,正常会输出usage: git credential-osxkeychain <get|store|erase>
  • 设置git config --global credential.helper osxkeychain
  1. 将本地的keychain删除
    • 打开Spotlight(command + space)
    • 输入keychain,实际打开的是keychain Access.app
    • 在列表中搜索github.com,移除
  2. 重新git pull,要求输入用户名和密码,密码即刚刚生成的access_token
  3. 参考

git pull报错:fatal: unable to access

  1. git pull报错:fatal: unable to access ‘https://github.com/liusirdotme/liusirdotme.git/': Failed to connect to github.com port 443 after 21047 ms: Couldn’t connect to server
  2. *查询最快的ip,我拿到的115.238.229.131 *
  3. 修改hosts,添加
    • IP1 github.global.ssl.fastly.net
    • IP2 github.com
  4. 刷新DNS:ipconfig/flushdns
  5. 参考链接
1
2
3
4
5
6
7
8
9
10
11
push/pull好慢
* 使用ipaddress.com
* [查询最快的ip](https://www.ipaddress.com/),我拿到的`115.238.229.131`
* 修改`/etc/hosts`,添加`115.238.229.131 github.global.ssl.fastly.net`
* 刷新本地DNS缓存`sudo killall -HUP mDNSResponder`
* 使用tool.chinaz.com
* 在浏览器打开`http://tool.chinaz.com/dns`
* 输入`github.com`
* 在输出列表中选择TTL值小的IP地址复制,如`13.250.177.223`
* 粘贴到hosts文件`13.250.177.223 github.com`
* 刷新下DNS缓存

git报错:fatal:detected dubious ownership in xxx

1
2
3
4
5
6
7
8
9
10
11
"git log"失败,错误代码 128:fatal:detected dubious ownership in
repository at d:/phpstudy_pro/www/abandon/abyss weixin_pc'
d:/phpstudy_pro/www/abandon/abyss weixin_pc' is owned by:
builtin/administrators (s-1-5-32-544)
but the current user is:
liusir/administrator
(s-1-5-21-1136792711-3309325150-3176985401-500)
to add an exception for this directory,call:
git config --global--add safe.directory
d://phpstudy_pro/www/abandon/abyss_weixin_pc
(d:/phpstudy_pro/wwwwabandonlabyss weixin_pc)
  • git config –global –add safe.directory D:/phpstudy_pro/WWW/abandon/abyss_weixin_pc
  • git config –global –add safe.directory “*”

修改commit message

  1. 修改已commit未push最近的提交

    • git commit –amend
    • 仅修改message:git commit --amend --message="new message"
    • 仅修改author:git commit --amend --author="new author@sm.com"
  2. 修改已commit已push最近的提交

    • git commit –amend
    • git push –force-with-lease
  3. 修改历史提交commit的信息


合并

在Git中整合来自不同分支的修改主要有两种方法:merge以及 rebase。

一、merge

  1. git merge命令用于合并指定分支到当前分支,如将dev分支合并到
    • git checkout master
    • git merge dev
    • git merge –abort,比如因为各种原因不想merge了,直接取消

二、rebase

  1. git rebase命令把本地未push的分叉提交历史整理成直线
  2. 不要对在你的仓库外有副本(已推送到远程仓库)的分支执行变基

三、参考

  1. 参考一

回滚

一、reset

  1. 作用:修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本

二、revert

  1. git revert是用于“反做”某一个版本,以达到撤销该版本的修改的目的。

    比如,我们commit了三个版本(版本一、版本二、 版本三),突然发现版本二不行(如:有bug),想要撤销版本二,但又不想影响撤销版本三的提交,就可以用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西。

  2. 作用

    通过反做创建一个新的版本,这个版本的内容与我们要回退到的目标版本一样,但是HEAD指针是指向这个新生成的版本而不是目标版本

  3. 实现

    • git revert -n commit-id
    • git commit -m 版本名
    • git push

三、各种恢复

  1. 未add

    • 撤销某个文件git checkout -- filename
    • 撤销所有修改git checkout .
      • 放弃掉所有还没有加入到缓存区的修改:内容修改与整个文件删除
      • 不会删除刚新建的文件
  2. 已add

    • 撤销某个文件git reset HEAD filename
    • 撤销所有修改git reset HEAD .
      • 用来清除git对于文件修改的缓存,相当于撤销git add命令
      • 继续撤销则参看未add情况
  3. 已commit

    • 撤销到上一个状态git reset --hard HEAD^
    • 撤销到任一个状态git reset --hard commit_id
    • 强推git push -f

Git 撤销操作汇总表

命令 作用 影响范围 危险等级 备注
git checkout -- . 丢弃工作区已跟踪文件的修改,恢复到暂存区状态 已跟踪文件的本地改动;不影响暂存区、不删除untracked文件 ⭐⭐ Git 2.23之前的传统写法,新版推荐用git restore .替代
git restore . 新版命令,丢弃工作区已跟踪文件修改 已跟踪文件本地改动;不影响暂存区,不删除untracked文件 ⭐⭐ Git2.23+支持;撤销暂存:git restore --staged .
git clean -f 删除未跟踪(untracked) 的文件 只删除Git从未管理过的新建文件;不影响已跟踪文件 ⭐⭐⭐ -f强制删除;预览:git clean -n -f;删除后Git无法找回
git revert <commit-id> 新建一条反向提交,抵消某次commit的改动 生成新commit,原有提交记录保留,不修改历史 ⭐ 公共分支首选,不改写提交历史
git reset 重置HEAD指针,移动暂存区,可选保留工作区改动 分3种模式,可改写提交历史 ⭐⭐⭐
• git reset --soft:移动HEAD,保留暂存+工作区
• git reset(默认mixed):移动HEAD,取消add,保留工作区
• git reset --hard:移动HEAD,清空暂存+工作区

一键重置组合(回退到最近一次commit,清除本地所有修改+未跟踪文件)

1
2
3
git reset HEAD .
git restore .
git clean -f

git reset --hard 和 git clean -f 会永久丢失本地未提交内容,执行前务必确认。


变基

⚠️ 前置红线:rebase 会重写 commit 哈希,只用于本地未推送 / 自己私有分支;公共分支、别人已经拉取过的提交严禁 rebase!

一、修改提交信息(2种场景)

场景1:只修改【最近1次】提交备注(不需要rebase)

命令:

1
git commit --amend

作用:覆盖上一次 commit;如有新 add 的文件,会一并并入本次提交。
操作:

  1. 执行命令,进入vim
  2. i 编辑注释
  3. Esc → :wq 保存退出

场景2:修改【历史某一条/多条】commit备注(交互式rebase)

命令:

1
2
3
4
# 方式1:指定父哈希
git rebase -i <目标commit_hash>^
# 方式2:简写,最近n条提交,例如最近3条
git rebase -i HEAD~3

作用:进入交互式编辑列表
操作:

  1. 把目标 commit 前面 pick → reword(简写r)
  2. :wq 保存退出,依次修改每条commit备注
  3. 无需 git commit –amend,改完自动完成

二、修改历史提交的【代码内容】(交互式rebase edit)

场景:很久以前的commit写错代码,需要回溯修改代码+提交信息

1
2
git rebase -i <目标commit_hash>^
# 或者 git rebase -i HEAD~n

作用:停留在目标commit节点,允许修改源码
操作:

  1. 将目标 commit 的 pick → edit(简写e)
  2. :wq 保存退出
  3. 修改代码 → git add
  4. 修改提交备注:git commit --amend
  5. 继续下一个待edit提交:git rebase --continue

    多个edit会逐个暂停,重复3~5步骤;中途不想改:git rebase --abort

三、合并多条历史提交(squash / fixup)

场景:本地一堆零散小commit,合并成一条干净提交,再推远程

1
git rebase -i HEAD~n
  • squash(s):把当前commit合并到上一条;保留两条commit注释,可以编辑汇总
  • fixup(f):把当前commit合并到上一条;丢弃当前commit注释,只保留上一条
    操作:
  1. 把要被合并的commit前面改为 s / f(保留第一条为pick)
  2. :wq 保存,squash会弹出编辑器合并备注
  3. 确认后完成合并

四、删除历史提交记录 drop

场景:本地提交里有一条错误提交,直接删掉这条记录

1
git rebase -i HEAD~n

操作:

  1. 目标commit前面 pick → drop(d)
  2. :wq 保存,该提交直接从历史移除

五、分支变基(非交互式 rebase,常用在合并分支)

场景:基于旧main分支开发,main有新提交,把当前分支所有提交移到main最新节点后面,代替merge,提交线更整洁

1
git rebase main

作用:把当前分支的提交,逐个在main最新代码上重演
冲突处理:

  1. 出现冲突 → 修改冲突文件 → git add
  2. 继续变基:git rebase --continue
  3. 放弃本次变基,恢复原样:git rebase --abort

六、rebase 通用中断命令(所有交互式/分支rebase都适用)

命令 作用 使用场景
git rebase --continue 继续执行rebase 解决冲突后 / edit模式修改完commit后
git rebase --abort 放弃本次rebase,完全回滚到rebase之前状态 rebase操作一半,不想继续了、冲突解决不了

七、补充:rebase 交互式指令速查

指令 简写 作用
pick p 使用该提交,不作任何修改
reword r 仅修改commit备注,不改代码
edit e 修改提交代码/备注
squash s 合并到上一条,保留注释可编辑
fixup f 合并到上一条,丢弃当前注释
drop d 删除这条提交

八、风险清单

  1. 已经push到公共远程分支,不要rebase,哈希改变会导致团队历史错乱
  2. 强行推送重写后的历史(慎用,私有分支可用)
    1
    git push --force-with-lease

    –force-with-lease 比 –force 安全,会校验远程有没有别人新增提交


工作流

一、概念

      工作流(Workflow)指业务过程的部分或整体在计算机应用环境下的自动化,是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。在计算机中,工作流属于计算机支持的协同工作(CSCW)的一部分。后者是普遍地研究一个群体如何在计算机的帮助下实现协同工作的。工作流主要解决的主要问题是:为了实现某个业务目标,利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。

二、分类

  1. 中心化的工作流:和Subversion一样,中心化的工作流将中央仓库作为项目中所有修改的唯一入口,默认的开发分支叫做master,所有更改都被提交到这个分支,这种工作流不需要master之外的其它分支。开发者将中央仓库克隆到本地后开始工作,在本地项目副本中可以像SVN一样修改文件和提交更改;不过,这些新的提交被保存在本地,它们和中央仓库完全隔离。为了向官方项目发布修改,开发者将他们的本地master分支推送到中央仓库,这一步等同于svn commit。

  2. 基于功能分支的工作流:Feature分支工作流同样使用中央仓库,master同样代表官方的项目历史,和中心化的工作流不同的是开发者每次进行新的工作时创建一个新的分支。Feature分支应该包含描述性的名称,比如animated-menu-items或issue-#1061,每个分支都应该有一个清晰、高度集中的目的。

  3. Gitflow工作流:GitFlow工作流仍然使用中央仓库作为开发者沟通的中心。和其他工作流一样,开发者在本地工作,将分支推送到中央仓库,唯一的区别在于项目的分支结构,可以分为历史分支、功能分支、发布分支、维护分支。

  4. Fork工作流:Fork工作流其它工作流不同,它不是使用唯一的服务端仓库作为中央代码库,而是给予每个开发者一个服务端仓库。也就是说每个贡献者都有两个Git仓库:一个私有的本地仓库和一个公开的服务端仓库。开发者通过执行克隆操作将远程公共仓库复制到本地,这是有的开发环境。做完修改后准备提交时,代码将被推送到自己的公开仓库而非官方仓库,然后向主仓库发起一个Pull Request,项目维护者审查没问题后进而合并到官方仓库。

  5. dev=>test=>pre=>master=>release

三、参考

  1. 参考一

Git和GitLab对比

对比项 裸 Git 仓库(bare) GitLab
底层 原生 Git,无额外程序 底层就是裸 Git 仓库,外加 Ruby/Go 服务
Web 界面 ❌ 没有,纯命令行 ✅ 完整 Web UI,浏览代码、提交历史
用户权限 仅依赖服务器系统账号(ssh / 文件权限),权限粗糙 ✅ 精细权限:项目 / 组级别,guest/reporter/developer/maintainer/owner
代码评审 ❌ 原生不支持,只能 push 代码 ✅ Merge Request,评论、代码行批注、评审流程
CI/CD ❌ 无 ✅ 内置 GitLab CI 流水线
Issue/Wiki/看板 ❌ 无 ✅ 全部内置
WebHook 需要自己写脚本监听 ✅ 内置 Webhook 配置界面
操作方式 ssh /git 协议,命令行 git push/pull git 协议 + ssh+https,命令行 + Web 操作
部署成本 极低,只需要安装 git 高,需要数据库、Redis、Runner,资源占用大
适合场景 小团队简单代码托管,只需要 git 推拉代码 企业 / 团队完整研发协同

更换远程仓库地址

一、报错

  1. 新建远程仓库
  2. 根据指引处理
1
2
3
4
5
6
7
echo "# game" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/liusirdotme/game.git
git push -u origin main
  1. 由于各种原因更换远程仓库,已经执行了上面的命令,再次执行会报错:
1
error: remote origin already exists.

二、处理

  1. 方案1:直接修改
1
2
git remote set-url origin https://github.com/liusirdotme/game.git

  1. 方案2:先删再加
1
2
3
4
5
# 删除旧的origin
git remote rm origin

# 再添加
git remote add origin https://github.com/liusirdotme/game.git
  1. 方案3:保留并新增
1
git remote add github https://github.com/liusirdotme/game.git
  1. 其他操作
1
2
git remote -v #查看远程
git push -u origin main #推送远程 如果分支是master就用 git push -u origin master