Skip to content
Go back

Git

Updated:  at  22:38

On this page

基本操作

commandremark
git clone -b <branch name> <url>克隆指定分支
git add <file>可反复多次使用,添加多个文件
git commit提交
git status工作区的状态
git diff查看修改内容
git reset —hard commit_id版本恢复,HEAD 指向的版本就是当前版本
git checkout — file未添加到暂缓区,丢弃工作区的修改
git log查看提交历史
git reflog查看命令历史,以便确定要回到未来的哪个版本
git rm删除
git remote -v查看远程库信息
分支😊
git branch -a查看远程分支
git branch查看分支
git branch <name>创建分支
git checkout <name>切换分支
git checkout -b <name>创建 + 切换分支
git merge <name>合并某分支到当前分支
git branch -d <name>删除分支
git log —graph —pretty=oneline —abbrev-commit查看分支的合并情况
git merge —abort终止 merge
git checkout -b branch-name origin/branch-name在本地创建和远程分支对应的分支
git fetch从远程获取最新版本到本地,不会自动 merge
git pull更新分支 从远程获取最新版本并 merge 到本地
git push origin test把分支推到远程分支
tag😊
git tag <name>用于新建一个标签,默认为 HEAD,也可以指定一个 commit id
git tag -a <tagname> -m “qaq…”指定标签信息
git tag -s <tagname> -m “qaq…”用 PGP 签名标签
git show <tagname>查看标签详细信息
git tag可以查看所有标签
git push origin <tagname>推送一个本地标签
git push origin —tags推送全部未推送过的本地标签
git tag -d <tagname>删除一个本地标签
git push origin :refs/tags/<tagname>删除一个远程标签
other😊
ssh-keygen -R github.com删除 known_hosts 配置
ssh -T [email protected]测试连接

checkout

git checkout 提交记录

git checkout main^

git checkout main^^

git checkout HEAD~4

git checkout -b foo o/main;

git branch -u o/main foo

commit

Branch

git branch -f 用于强制将一个分支指向另一个特定的提交,无论是否会导致非快进更新(non-fast-forward)

git checkout -b 命令用于创建一个新的分支并立即切换到该分支

git switch 命令用于切换到另一个分支或创建并切换到一个新分支

对比:

Git 的分支也非常轻量。它们只是简单地指向某个提交纪录 —— 仅此而已

“我想基于这个提交以及它所有的 parent 提交进行新的工作。”

git push origin <source>:<destination> source 推送到 destination

git fetch origin <source>:<destination> 拉取 source 到 destination

git push origin :foo 删除远程 foo 分支

git fetch origin :foo 本地创建 foo 分支

git pull origin foo 相当于:git fetch origin foo; git merge o/foo

git pull origin bar:bugFix 相当于:git fetch origin bar:bugFix; git merge bugFix

merge

在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个 parent 节点。翻译成自然语言相当于:“我要把这两个 parent 节点本身及它们所有的祖先都包含进来。”

rebase

优点:

缺点:

比如, 提交 C1 可以被 rebase 到 C3 之后。这看起来 C1 中的工作是在 C3 之后进行的,但实际上是在 C3 之前。

一些开发人员喜欢保留提交历史,因此更偏爱 merge。而其他人(比如我自己)可能更喜欢干净的提交树,于是偏爱 rebase。仁者见仁,智者见智。

将一个分支的更改重新应用到另一个分支的基础上

实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰

rebase vs merge

分离 HEAD 状态Detached HEAD)是指在 Git 中,你的 HEAD 指向了一个具体的提交,而不是某个分支。这意味着你当前所做的更改是基于一个特定的提交,而不是在一个分支上进行的

~ 向上返回几代

^ 合并提交记录正上方的那个提交记录

HEAD 是一个对当前所在分支的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。

HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。

通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用

强制修改分支位置

git branch -f main HEAD~3

撤销变更

用于回退或移动当前分支的提交历史和暂存区的状态。它可以改变 HEAD 指向的位置,并根据使用的选项来调整暂存区和工作目录的内容

在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。

主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。接下来咱们逐个进行讲解。

采用传入:git checkout —theirs .

采用当前:git checkout —ours .

整理提交记录

“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”

git cherry-pick 将某个分支的一个或多个提交应用到当前所在的位置(HEAD),只要不是 HEAD 上游的提交就没问题

git rebase -i HEAD~i : pick/omit/sort 手动修改、重排、合并、删除或修改提交记录。它是一个非常强大的工具,用于清理和优化提交历史

git reset —hard C3'''

git checkout -B main C3'''

git tag

git describe 的​​语法是:

git describe <ref>

<ref> 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会使用你目前所在的位置(HEAD)。

它输出的结果是这样的:

<tag>_<numCommits>_g<hash>

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。

当 ref 提交记录上有某个标签时,则只输出标签名称

远程仓库

远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据

git fetch 完成了仅有的但是很重要的两步:

更新到我们的工作当中

git fetch; git rebase o/main; git push
git pull --rebase; git push

git fetch; git merge o/main; git push
git pull; git push

git push

git push origin main

no-fast-forward

merge 时生成一个新的 commit,这样,从分支历史上就可以看出分支信息

git merge --no-ff -m "merge with no-ff" dev

丢弃更改

如果修改未添加到暂缓区,想丢弃工作区的修改:

  1. git checkout -- file

如果修改已经添加到了暂缓区,想丢弃修改:

  1. git reset HEAD file
  2. git checkout -- file

如果修改已经提交到了版本库:

  1. git reset --hard commit_id 版本回退

git config

# 项目配置
git config --local -l
# 用户配置
git config --global -l
# 系统配置
git config --system -l

关联远程仓库

1.git remote add origin git@server-name:path/repo-name.git

2.git push -u origin master:第一次推送

3.git push origin master:以后的推送

Stash

暂存工作区和暂存区的修改

  1. git stash:存储工作现场

  2. git stash pop:恢复并删除 stash 内容

  3. git stash apply:恢复工作现场

  4. git stash list:查看 stash 内容

设置代理

https://hellodk.cn/post/975

https://v2ex.com/t/843383

ssh

~/.ssh/config 文件

Socks 代理

mac

Host github.com
HostName github.com
ProxyCommand nc -v -x 127.0.0.1:1086 %h %p

windows

Host github.com
  ProxyCommand connect -H 127.0.0.1:7890 %h %p

http

指定 github.com

git config --global http.https://github.com.proxy http://127.0.0.1:8080
git config --global https.https://github.com.proxy http://127.0.0.1:8080

git config --global http.https://github.com.proxy socks5://127.0.0.1:7890
git config --global http.https://github.com.proxy socks5h://127.0.0.1:7890

取消

git config --global --unset http.proxy
git config --global --unset http.https://github.com.proxy
git config --global --unset https.proxy
git config --global --unset https.https://github.com.proxy

查看提交次数

总提交次数:git log --oneline | wc -l

某个用户提交次数:git log --author="用户名" --oneline | wc -l

每个用户提交次数:git shortlog -s -n

某个用户时间范围内提交次数:git log --author="用户名" --since="2014-07-01" --oneline | wc -l

代码量统计

行数

git ls-files | xargs cat | wc -l

个人代码量:

git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

每个人代码量

git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done

同步更新 fork 的仓库

  1. 添加一个将被同步给 fork 远程的上游仓库
    • git remote add upstream https://github.com/apache/flink.git
  2. 从上游仓库 fetch 分支和提交点,传送到本地,并会被存储在一个本地分支 upstream/master
    • git fetch upstream
    • 指定分支 git fetch upstream 18-3-1
  3. 在本地分支上,执行合并
    • git merge upstream/master
  4. 推送到远程
    • git push origin master

多账号问题

一台电脑连接多个 GitHub 账号下的仓库

Git 如何切换账户

解决 切换 github 账号后无法 push 的问题

Git 最著名报错“ERROR: Permission to XXX.git denied to user”终极解决方案

Git’s famous “ERROR: Permission to .git denied to user”

crlf

// 拒绝提交包含混合换行符的文件 (一般设置为true)
git config --global core.safecrlf true
// 提交检出均不转换
git config --global core.autocrlf false

core.autocrlf

true:提交时改成 LF,检出时改成 CRLF

input:提交时改成 LF,检出时不改

false:提交时是什么就是什么,不改换行符,检出时也不改 (默认值)

core.safecrlf

true: 拒绝提交包含混合换行符的文件(会提示 Fatal:xxx)

false: 允许提交包含混合换行符的文件

warn: 提交包含混合换行符的文件时给出警告 (默认值)

.gitattributes 文件中

注释

* text=auto

或改为:

* text=eol=lf

no matching host key type found. Their offer: ssh-rsa

配置好公私钥之后,仍然无法直接用 git ssh 的方式,下载代码,解决:

.ssh/config 增加以下二项

Host x.x.com
  HostKeyAlgorithms ssh-rsa
  PubkeyAcceptedKeyTypes ssh-rsa

fatal: early EOF fatal: fetch-pack: invalid index-pack output

<https://stackoverflow.com/questions/21277806/fatal-early-eof-fatal-index-pack-failed>

# Git 服务器的内存不够了,导致压缩传输数据失败,服务器直接挂了
# 整数 -1..9,表示默认压缩级别。 -1 是 zlib 默认值。0 表示不压缩,9 是最慢的。
# 关闭压缩
git config --global core.compression=0
# 下载最近一次提交
git clone --depth 1 `<repo_URI>`
# 拉取剩余部分
git fetch --unshallow 
# 常规拉取
git pull --all

git flow

https://nvie.com/posts/a-successful-git-branching-model/

release 分支理解为 提测分支。来自 develop

如果测试有 bug,在 release1.2 分支修复,合并回 develop,有冲突解决

测试完成要发布了,分别合并回 develop 和 master

问题:

1、从 master 拉分支,分支名:bugfix/xxxxxx feature/xxxxx

2、开发自测完将新拉分支合到 dev,开发环境自测一波

3、开发环境自测没问题,将新拉分支合到 test,用 test 发预发环境

4、测试发现 bug/需求调整等,重复 2,3 步骤

5、测试通过,将此次拉的分支合到 master,如需发正式,从 master 发

git worktree

git worktree add <新路> -b <新分支>
git worktree add <新路> -b <新分支> <指定分支>
git worktree add ../worktree-fixa -b feature/fixa release

从 release 分支拉一个新分支 feature/fixa,放到../worktree-fixa 目录

submodule

https://git-scm.com/docs/git-submodule

https://git-scm.com/docs/gitsubmodules

https://juejin.cn/post/7154398231449829383

添加子模块

# 会自动拉取代码   .gitmodules添加lodash
git submodule add [email protected]:lodash/lodash.git lodash

更新

新 clone 的项目不会自动 clone submodule

git submodule init 用来初始化本地配置文件,将.gitmodules中关于[submodule]的部分拷贝到.git/config文件中。
git submodule update 根据项目的.gitmodules文件,抓取远程仓库的代码。
git submodule update --init --recursive  初始化,拉取所有子模块

git submodule update —remote:这个命令会更新子模块并将其切换到最新的远程提交。

git submodule update:使 submodule 的分支处于主项目里指定的 commit id。可能并不是拉 submodule 的 master 最新代码

删除

# 清空lodash目录(lodash文件夹本身未删除),移除$GIT_DIR/config中的lodash
git submodule deinit lodash
# .gitmodules移除lodash,删除lodash目录,config未修改
git rm lodash

# 手动删除 $GIT_DIR/modules/<name>/

submodule vs subtree

https://stackoverflow.com/questions/31769820/differences-between-git-submodule-and-subtree

submodule is link

subtree is copy

mono-repo vs multi-repo

gist

github secret gist

只有知道 url 的才能看到

问题

https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/


Suggest Changes

Previous Post
memory leak
Next Post
react native

Most Related Posts

  • javascript transpiler

    Published:  at  23:29

    javascript transpiler

  • preserveSymlinks in vite

    Updated:  at  17:15

    preserveSymlinks in vite

  • nginx

    Updated:  at  14:06

    nginx

  • Linux Basic Command

    Updated:  at  00:20

    Linux Basic Command

  • termux

    Published:  at  21:58

    termux