==了解== 熟悉 掌握 精通

基本流程操作

初始化

  • git clone <http path> 直接凭空拉远程项目
  • git init 在已存在的文件夹使用,生成一个仓库
  • git remote add origin <SSH path> 连接到此path的远程仓库,本地须是仓库
  • 忽略. 新建的文件名是 .gitignore
    • 符合正则,通配符那些。忽略文件夹就直接: folder/
    • 可以建多个.gitignore,它负责的范围就是它所在路径为根遍历的树。
  • 本地全局设定从master改成main,和github对应
    • 两种方式改动:
      • .gitconfig里添加
        [init]
            defaultBranch = main
        
      • 用命令git config --global init.defaultBranch main
    • 但是已经生成的仓库还得手动改:
      1. 查看本地分支 git branch
      2. 如果不在master 则切到master git checkout master
      3. git branch -M main

一周期流程

git clone 或者 git pull

## 上传
git add .
git commit -m '注释'
git push origin main

产生冲突了怎么办

pull的时候冲突了

  • 不想要本地文件了
    git clean -f  # 删除本地同名文件
    git pull  # 拉取
  • 强制覆盖本地文件
    git fetch --all
    git reset --hard origin/main
  • 两地的更改都想保留
    git add *  # 将所有文件添加到git的跟踪列表中
    git stash   # 保存本地更改
    git pull  # 拉取
    git stash pop  # 合并

如果存在冲突,运行完pop之后文件就会标记冲突的地方,然后手动更改。然后再
git add <刚刚的文件>开始按流程push。

pull时错误:需指定合并方式

git push了报错有远程分歧,然后又git pull提示报错:

fatal: Need to specify how to reconcile divergent branches.

说明此时有冲突。
git fetch,下载下来,先不合并
然后可用git status查看哪些文档修改了,哪些文档本地远程同时修改了产生冲突了。
此时该冲突文档一定有<<<<<<< HEAD这种东西,然后手动修改。
修改好了之后就git add .那一套push。

状态检查

查看本地和远程区别

git fetch
git diff origin/branchname

查看本地和远程的差异提交

git fetch
git log origin/branch_name..branch_name

查本地和远程分支的同步状态

git status

显示是否需要拉取(pull)远程更新,或推送(push)本地更改。

查远程仓库的详细信息

git remote show origin

显示哪些本地分支落后于远程分支,哪些需要推送。

git 配置文件

git 有三个配置文件

  • system 系统
    系统所有用户都会生效,一般在安装路径下
    查看此文件路径:git config -e --system
    我的在:/opt/homebrew/etc/gitconfig
  • global 全局
    当前用户生效
    路径:$HOME/.gitconfig
  • local 本地
    仅当前项目生效
    路径:(当前项目)/.git/config

优先级:local > global > system

设置用户名密码的时候使用的命令git config --global <用户名>,global意思就是改在了global config里

多账户设置

添加额外的rsa公私钥
ssh -keygen -t rsa -C "email@work.com" -f "id_rsa_work_user"

全局设置

全局设置就是不用每次配置切换

在ssh config ~/.ssh/config中添加多个账户

# Account 1
Host <nameA>  # 本机域名 自己设 比如account1
	HostName github.com  # 固定,真正的域名或ip,网站地址
	User git  # 固定
	IdentityFile ~/.ssh/id_rsa_account1

# Account 2
Host <nameB> # 本机域名 自己设 比如account2
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_account2

==!在使用的时候比如clone,所有git@github.com的地方都换成 git@[HOST]==,
例如:
git clone git@ccount1:username/repo.git
一个账户的时候都是git@github.com,因为它默认的host是github.com

每次单独链接sshkey

可以不配置全局配置,每次切换操作:

ssh -add -D  # remote 全部配置
ssh -add ~/.ssh/id_rsa_yours  # 添加相应的key

如果要换已存在仓库的账户:

git remote rm origin  # 如果之前已经和远程建立过链接,需要先清除当前连接
git remote add origin git@[HOST]:[github上的名字/仓库名字.git]  # 重新建立连接

查看有没有连接好:
ssh -T git@[Host]
如果连接好了会返回:
Hi xxx!....

远程配置

查看本地对应的远程仓库:
git remote -v

如果不匹配,就重新设置
git remote set-url origin git@github.com-worker_user:worker_user/repo_name.git

新建仓库本地配置远程仓库
git remote add origin git@github.com-work_user:work_user/repo_name.git

ssh多账户、git多账户,ssh/http及切换流程

ssh多账户,是指可能有工作、个人等多个github远程账户,远程ssh连接的时候用,和提交作者无关,只用初始化的时候连接对应的HOST就可以了!
HOST在/.ssh/configHOST设置。后续切换不用命令,只用进入对应的文件夹。
假设HOST的名字是myhost,github上本账户的名字是mygithub(那么此项目地址应该是mygithub/project.git), 注意clone的时候是git clone git@myhost:mygithub/project.git就行了。

git多用户,是用来记录同一个/不同项目中提交作者的信息,和ssh连接无关。有系统、全局、本地三个设置,指的是/gitconfig.git/config里的[user],设置name和email。可以和ssh的账户对应但根上无关。查看用:

# 设置
git config (--global) user.name 
git config (--global) user.email

# 查看
git config --global --list  # 全局
git config --list  # 项目

http协议下,每次push都要输用户名密码like
Username for 'https://github.com': 让你输,但是!
这个不是输用户名的,而是在这个地方

alt text

输入这个token。没有就新建一个。
密码直接空。

不是很方便,所以需要 —— http切换为ssh协议:

# 查看当前远程 URL
git remote -v

# 更改远程 URL 为 SSH
git remote set-url origin git@github.com:username/repo.git

# 验证更改
git remote -v

# 测试 SSH 连接
ssh -T git@github.com

github协作模式

添加collaborator 比较直观就不记录了。
这里记录一个协作权限操作的问题。

clone别人项目

前置知识是clone,https url和ssh url的区别:

  • HTTPS:不管是谁,拿到url随便clone,但是在push的时候需要验证用户名和密码;
  • SSH:clone的项目你必须是拥有者或者管理员,而且需要在clone前添加SSH Key。

clone 别人项目方式

其实一般普通下载就可以了,此情况是想要提交代码,协作修改项目的情况。

  • 加入协作者
    具体方案是 项目拥有者or管理员添加你为collaborator,然后自己在邮件里同意。
  • fork
    1. 把想clone的代码fork到自己的库,再clone
    2. 提交。本地改完之后先提交到自己的库,再点击pull request提交pull请求。

协作者clone 私有库方案

协作者clone public库试了一下没问题,但是当我作为collaborator 去clone仓库拥有者的库的时候,遇到了问题:public库正常,但private库报错:没有权限。

目前查到的结局办法是:用https的方式clone,并附token_。步骤如下:

  1. 设置token
    路径:github.com → setting → personal access tokens → generate new token(现在有两个选项了 就选general就行) → 生成
    勾选我就全勾选了因为当前要用的是我自己的项目
  2. clone项目
    格式:git clone https://<生成的token>@<想下载项目的原路径>
    这里<想下载项目的原路径>github.com/<repo_owner_name>/<repo_name>.git

简单概念

分区

git 分区名字必须记住,这个用的很多

  • working dir,工作区,就是包括自己写代码的文件夹
  • stage,暂存区,
  • history,历史区

流程依次往后。
本地到暂存,用 add;暂存回本地,用checkout;
暂存到历史,用 commit;历史回暂存,用reset;
本地直接到历史,用 commit -a;历史回本地,用checkout 指定head;

历史的回退,实际上是将指针指向之前的head。

其它注意的点

当远程仓库与本地仓库不同时,如果强制push本地,是全部覆盖,而不是追加,远程有本地没有的文件,将会全部消失。

基础命令

追加提交:git commit --amend

分支

创建:git branch <name> # 查看也是这个
切换:git switch <name> # 本来是checkout 但这个名字太抽象了 我决定用新版命令
合并:git merge <othername> # 这里是指将othername的分支,并到当前所在分支 主从关系这里有。要想哪个为主要先切到哪条。
合并系列顺序:创建并切到other分支 ➡️ 提交other ➡️ 切回主分支并提交 ➡️ merge other

复制式合并:git rebase <mainname> # 这里是将当前分支归顺到目标分支上去,跟上面主从一样,但视角是反的。
复制系列顺序:创建并切到other分支 ➡️ 提交other ➡️ 切回主分支并提交 ➡️ 切回other ➡️ rebase main

一股脑复制:git cherry-pick <想挪的所有分支依次> # 要按顺序。被挪的地方当前分支的下面
一股脑复制删除:git rebase -i HEAD~<x> # -i是点开 可以编辑想要和不需要的节点

git rebase <A> <B>
相当于
git switch <B>
git rebase <A>
注意rebase 一参数的,相当于客人视角,给定主人地址,然后并过去
两参数是<主人地址> <客人地址> 的顺序。

此外,挪动是从它们的共同祖先开始的。

利用head挪动:
head目前感觉相当于当前指针,如果想将某个分支的当前指向停在任意节点,可以先将head指过去,再令当前分支指向head。
可以用hash值,也可以用相对路径。parent:^,x代祖先:~x

^x:平级的第几个爸爸,~x:竖着的第几代祖先
git checkout HEAD~^2~3:当前的爹的二号爹的爹的爹的爹

head挪过去:git checkout <hash值/HEAD ~x>
分支头再挪过去:git branch -f <分支名> HEAD~x # -f 强制挪动

branch这个命令就是可以用来将一个指针挪到指定位置。
上面这两行也相当于
git branch -f <A> <B>
这两个参数 是被挪的指针 是目标节点

注意这里面的A B 都可以自由的加^``~这些

想改之前的分支:
cherry-pick或者rebase

我个人觉得cherry-pick比较好理解,操作的都是本分支,命令中将想要的节点依次罗列就行了。想给哪个分支加点,就先switch到哪个下面就行。

branch 和 rebase都有一个git xxx <A> <B>这样的命令,两个区别是branch是挪动指针,rebase是复制过来。

rebase还有一个点,如果A和B在一条线上,B落后,要用rebase A B,即将A新commit的部分复制给B。而不能用branch。

撤销提交

指的是commit之后的回撤。
本地撤销:git reset <当前分支的parent> # 注意一定要加^, 是目标节点。比如main^
远程撤销:git revert <当前分支> # 注意是本身,因为原理是开一个子节点和父节点一样,而不是直接回父。

标签

添加标签:git tag <分支名字> <标签名字>
标签是为了给版本打tag,只有重大更新完成之后可以使用这个。

# 打标签
git tag -a v1.0.0 -m "release 1.0"
# 查看标签
git tag --list
# 将标签同步给remote
git push --tags

远程

远程叫法:/ <远程仓库名>/<分支名>

意思是 本地存的,和远程进度一样的节点的指针。
如果fetch,是从指向o/main的节点算起


下载:git fetch
git pull = git fetch + git merge
git pull origin foo
相当于:
git fetch origin foo; git merge o/foo

如果本地尚未明晰merge哪个,就先把远程fetch下来。
如果要检查远程和local的区别,必须先fetch:

git fetch # 先fetch
git diff origin/branch_name  # 看本地和远程差异
git log origin/branch_name..branch_name  # 看本地和远程分支之间的差异提交记录。

merge和rebase的区别是:merge显示合并的样子,rebase是直接挪的复制过来,变成一条线

git merge A,是将A合并至当前分支。主人视角。

推送:git push origin <localname>:<remotename>
这个命令暗含了远程追踪。如果俩名字一样,可以省略成一个名字。如果远程分支不存在,也可以用这个命令新创建。

空:
给远程推空可以删除分支:git push origin :<name> # 删除远程name
给本地拉空可以新建分支:git fetch origin :<name> # 新建本地name

系统配置 git config

查看:git config <内容>,<内容> 可以是 --list,也可以是具体参数。
增删:git config <范围> <动作> <参数 (值)>
范围是 --global--local等,动作是--add --unset
$ git config --local -–unset site.name

版本管理

概览:阮一峰:Git分支管理策略
进化:Arganzheng’s Blog:Git分支管理策略
实例:一个 Git 分支协作模式的进化故事
补充:唐玥璨:GIT分支管理办法

bug记录

docker命令行总结

Git的基本使用命令