当前位置 : 首页 » 文章分类 :  开发  »  Git-常用命令

Git-常用命令

git基本操作笔记

《Pro Git》中文版,Git官方资料
https://git-scm.com/book/zh/v2

Git教程 - 廖雪峰
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

Git教程 - 易百教程
http://www.yiibai.com/git/


其他

git统计脚本

所有提交者及其次数

查看当前分支所有提交者及其提交次数,按次数由高到低排序

git log | grep "^Author: " | awk '{print $2}' | sort | uniq -c | sort -k1,1nr

统计某个人的代码提交行数

git log --author="masikkk" --pretty=tformat: --numstat | awk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "增加的行数:%s 删除的行数:%s 总行数: %s\n",add,subs,loc }'

统计当前git用户的代码提交量,通过 git config --get user.name 读出当前用户

git log --author="$(git config --get user.name)" --pretty=tformat: --numstat | awk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "增加的行数: %s 删除的行数: %s 总行数: %s\n",add,subs,loc }'

统计某时间范围内的代码提交行数

git log --since='2020-07-01' --until='2020-09-14' --pretty=tformat: --numstat | awk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "增加的行数:%s 删除的行数:%s 总行数: %s\n",add,subs,loc }'

如果想统计某个人某时间范围内的代码提交行数,再加上 --author="masikkk" 即可

git log --author="masikkk" --since='2020-07-01' --until='2020-09-14' --pretty=tformat: --numstat | awk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "增加的行数:%s 删除的行数:%s 总行数: %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 "增加的行数: %s, 删除的行数: %s, 总行数: %s\n", add, subs, loc }' -; done

结果

masikkk    增加的行数: 9352, 删除的行数: 2384, 总行数: 6968
madaimeng    增加的行数: 3190, 删除的行数: 407, 总行数: 2783
devgou   增加的行数: 280, 删除的行数: 9, 总行数: 271

git lfs 大文件

https://git-lfs.com/

安装 git 大文件扩展 git-lfs
brew install git-lfs

Update your git config to finish installation:

  # Update global git config
  $ git lfs install

  # Update system git config
  $ git lfs install --system
==> Summary
🍺  /opt/homebrew/Cellar/git-lfs/3.4.0: 78 files, 13MB

设置 lfs 跟踪的大文件:
git lfs track “*.so”

使用 Git LFS 管理指定目录下的文件,追踪文件夹中的所有文件(包含文件夹)
git lfs track ‘path/to/folder/**’

追踪文件夹中的文件(不包含文件夹)
git lfs track ‘path/to/folder/*’

查看当前使用 Git LFS 管理的匹配列表
git lfs track

类似 git status,查看当前 Git LFS 对象的状态
git lfs status

枚举目前所有被 Git LFS 管理的具体文件
git lfs ls-files

执行
git lfs track ‘devops/tesseract-lib-4.1.3/
git lfs track ‘devops/tesseract-lib-5.2.0/

后会生成 .gitattributes
强烈建议将此文件纳入 git 仓库管理中。

This repository is over its data quota

带大文件的 git 仓库 push 到 GitHub 报错:
batch response: This repository is over its data quota. Account responsible for LFS bandwidth should purchase more data packs to restore access.

解决:
GitHub 页面,仓库配置,archives 配置,勾选 Include Git LFS objects in archives.


GitLab关联JIRA的issue

commit 触发器的关键字 Closes, Fixes, Resolves, 不区分大小写, 但 Jira Issue ID 是区分大小写的, JIRA-10 不能写成 jira-10。
例如
Resolves PROJECT-1
Closes PROJECT-1
Fixes PROJECT-1

https://docs.gitlab.com/ee/user/project/integrations/jira.html#jira-issues

批量更新当前目录下的git项目shell脚本

#!/bin/bash

# Find all git repositories and update it to the master latest revision
find . -name ".git" | cut -c 3-
for i in $(find . -name ".git" | cut -c 3-); do
    dir=$(dirname "$i")
    echo -e "\033[31m git pull in $dir \033[0m";
    (cd "$dir" && git pull);
done

命名为pull.sh,加上x执行权限,放在外层目录下,每次只需执行 ./pull.sh 即可更新当前目录下所有git项目

\033[31m\033[0m 是特殊的颜色代码,分别设置颜色为红色和重置颜色。-e参数让echo命令解释这些颜色代码

批量更新Git项目脚本
https://www.centos.bz/2017/10/%E6%89%B9%E9%87%8F%E6%9B%B4%E6%96%B0git%E9%A1%B9%E7%9B%AE%E8%84%9A%E6%9C%AC/

shell 更新所有git目录
https://blog.csdn.net/zxsted/article/details/17022689


git存储原理

Git 仓库位于项目根目录的 .git 文件夹,其中保存了从仓库建立(git init)以来所有的代码增删。 每一个提交(Commit)相当于一个 Patch 应用在之前的项目上,借此一个项目可以回到任何一次提交时的文件状态。

于是在 Git 中删除一个文件时,Git 只是记录了该删除操作,该记录作为一个 Patch 存储在 .git 中。 删除前的文件仍然在 Git 仓库中保存着。直接删除文件并提交起不到给 Git 仓库瘦身的效果。

在 Git 仓库彻底删除一个文件只有一种办法:重写(Rewrite)涉及该文件的所有提交。 幸运的是借助 git filter-branch 便可以重写历史提交,当然这也是 Git 中最危险的操作。 可以说比 rm -rf * 危险一万倍。

git count-objects 查看git磁盘占用

git-count-objects 计算解包的对象数量及其磁盘消耗
git count-objects [-v] [-H | --human-readable]

$ git count-objects -vH
count: 24
size: 192.00 KiB
in-pack: 16986
packs: 1
size-pack: 336.91 MiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytes

git filter-branch 对所有分支进行过滤操作

这个 git 命令在 Pro Git 中被称为 The Nuclear Option,也就是核弹级别的选项。因为使用这个命令,会覆写巨量的提交历史。所以在公共项目上要慎重使用,除非是你自己的项目。

git filter-branch [--setup <command>] [--subdirectory-filter <directory>]
        [--env-filter <command>] [--tree-filter <command>]
        [--index-filter <command>] [--parent-filter <command>]
        [--msg-filter <command>] [--commit-filter <command>]
        [--tag-name-filter <command>] [--prune-empty]
        [--original <namespace>] [-d <directory>] [-f | --force]
        [--state-branch <branch>] [--] [<rev-list options>...]

选项
--tree-filter 表示修改文件列表
--index-filter--tree-filter 类似,单无需检出,所以更快
--msg-filter 表示修改提交信息,原提交信息从标准输入读入,新提交信息输出到标准输出。
--prune-empty 表示如果修改后的提交为空则扔掉不要。例如从所有分支删除 password.txt 文件操作中,某次提交只修改了 password.txt,那么,这个修改在 git 执行 filter-branch 后会变成空提交。
--all 是针对所有的分支。

彻底删除文件避免磁盘占用

步骤一:从本地所有分支和提交历史中删除指定文件和文件夹

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch path-to-your-remove-file' --prune-empty --tag-name-filter cat -- --all

其中 path-to-your-remove-file 就是你要删除的文件的相对路径(相对于 git 仓库的跟目录), 替换成你要删除的文件即可. 注意一点,这里的文件或文件夹,都不能以 ‘/‘ 开头,否则文件或文件夹会被认为是从 git 的安装目录开始。
如果要删除的是文件夹,在 git rm --cached 命令后面添加 -r 选项变为 git rm -r --cache,表示递归的删除(子)文件夹和文件夹下的文件。

例如
1、删除所有分支和提交历史中的 password.txt 文件

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch password.txt' --prune-empty --tag-name-filter cat -- --all

2、删除所有分支和提交历史中的 image 文件夹

git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch image' --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch source/_技术文档' --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch source/_posts/_NIO/公司文档' --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch source/_posts/_NIO/个人文档' --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch source/_posts/_NIO/业务文档' --prune-empty --tag-name-filter cat -- --all

步骤二:强制推送到远程仓库
git push origin master --force --tags

步骤三: 清理和回收空间
虽然上面我们已经删除了文件, 但是我们的 repo 里面仍然保留了这些 objects(在 .git/objects 目录中), 等待垃圾回收(GC), 所以我们要用命令彻底清除它, 并收回空间。

Git如何永久删除文件(包括历史记录)
https://www.cnblogs.com/shines77/p/3460274.html


git init

重建现有仓库

如果曾经往 git 中提交过大文件,即使删除也无法释放空间,因为 git 会记录版本历史,如果不需要之前的提交历史,可以重建一下 git 仓库,就能释放空间了。
在项目根目录中执行

$ rm -rf .git # 删除git版本控制目录
$ git init # 创建git版本控制
$ git config user.email "you@example.com" # 配置本仓库的email,有全局配置则不需要
$ git config user.name "Your Name" # 配置本仓库的name,有全局配置则不需要
$ git add . # 将所有文件加入版本控制(.gitignore 忽略的除外)
$ git commit -m "重建仓库" # 提交
$ git branch -M main  # master分支改名为main分支
GitHub 页面上删除现有仓库,重建同名仓库
$ git remote add origin <your_github_repo_url> # 添加远程仓库
$ git push -f -u origin main # 强制推到远程main分支

git config

Git配置

git config -l 列出所有git配置

git config -l:列出所有Git配置
读取时,默认情况下从系统,全局和存储库本地配置文件读取这些值,而选项 --system--global--local--file <filename> 可用于告知命令从只有那个位置设置和读取。
写入时,默认情况下将新值写入存储库本地配置文件,并且可以使用选项 --system--global--file <filename> 来告诉命令写入该位置(可以指定为 --local,但这是默认值)。

git配置文件.gitconfig

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:

/etc/gitconfig 系统配置–system

/etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有--system选项的git config时,它会从此文件读写配置变量。

~/.gitconfig 用户配–global

~/.gitconfig~/.config/git/config文件:只针对当前用户。 可以传递--global 选项让 Git 读写此文件。

.git/config 项目配置–local

当前使用仓库的Git目录中的config文件(就是.git/config):针对该仓库。

每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
在 Windows 系统中,Git 会查找$HOME目录下(一般情况下是 C:\Users\$USER)的 .gitconfig文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。


user.name/user.email 用户信息配置

当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
很多 GUI 工具都会在第一次运行时帮助你配置这些信息。

不同项目配置不同用户信息

比如自己公司内部的项目提交时设置的用户名为自己的真实姓名,但是在github上提交时,可能不想暴露真实姓名,这时候就不能采用通用的配置了,就要单独设置每个项目的git配置。
由于每个git项目下都会有一个隐藏的.git文件夹 ,将终端的工作目录设置到,相应的项目根目录下,执行ls -all
命令,显示所有文件,即可看到.git的隐藏文件夹。通过cd .git 进入该目录,发现该目录下有个config文件,采用
open config 命令打开,添加如下配置:

[user]
    name = XXX(自己的名称英文)
    email = XXXX(邮箱)

保存,command+s 即可。这时候就为该项目配置了独立的用户名和邮箱,这时提交代码时,提交日志上显示的就是设置的名称,当然github这种会根据设置的邮箱来设置对应的用户名。
当然也可以通过命令行的方式(即要去掉–global参数)去设置单独的git配置,只需要在 .git 文件夹下。 例如执行如下命令:

git config user.name "xxxxx"
git config user.email "xxx@xx"

来修改当前项目提交代码时用到的用户名和邮箱。

如果全局的配置和当前项目的单独配置中出现相同的配置选项,比如全局和项目都设置了user.name ,那么在该项目中进行git操作时,会默认采用该项目配置的用户名。


core.autocrlf 换行符自动转换

1、本人在Windows系统上工作,同伴用其他系统时
假如你正在 Windows 上写程序,而你的同伴用的是其他系统(或相反),你可能会遇到 CRLF 问题。 这是因为 Windows 使用回车(carriage return, CR)和换行(line feed, LF)两个字符来结束一行,而 Mac 和 Linux 只使用换行(line feed, LF)一个字符。 虽然这是小问题,但它会极大地扰乱跨平台协作。许多 Windows 上的编辑器会悄悄把行尾的换行字符转换成回车和换行,或在用户按下 Enter 键时,插入回车和换行两个字符。

Git 可以在你提交时自动地把回车和换行(CRLF)转换成换行(LF),而在检出代码时把换行(LF)转换成回车和换行(CRLF)。 你可以用 core.autocrlf 来打开此项功能。 如果是在 Windows 系统上,把它设置成 true,这样在检出代码时,换行会被转换成回车和换行:

# 提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true

2、本人在Linux或Mac上工作时
如果使用以换行作为行结束符的 Linux 或 Mac,你不需要 Git 在检出文件时进行自动的转换;然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把 core.autocrlf 设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换:

# 提交时转换为LF,检出时不转换
git config --global core.autocrlf input

这样在 Windows 上的检出文件中会保留回车和换行,而在 Mac 和 Linux 上,以及版本库中会保留换行。

3、所有人都仅在Windows上工作时
如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 false 取消此功能,把回车保留在版本库中:

# 提交检出均不转换
git config --global core.autocrlf false

8.1 自定义 Git - 配置 Git
https://git-scm.com/book/zh/v2/自定义-Git-配置-Git


core.safecrlf 换行符检查

#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true

#允许提交包含混合换行符的文件
git config --global core.safecrlf false

#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

core.quotepath 中文文件名乱码

在默认设置下,中文文件名在工作区状态输出,查看历史更改概要,以及在补丁文件中,文件名的中文不能正确地显示,而是显示为\xxx\xxx 这种八进制的字符编码,比如:

git status
    modified:   "source/_posts/\345\267\245\345\205\267/Git-\346\223\215\344\275\234.md"

这是因为git对0x80以上的字符进行了quote
通过将Git配置变量 core.quotepath 设置为false,就可以解决中文文件名称在这些Git命令输出中的显示问题

#不对0x80以上的字符进行quote,解决git status/commit时中文文件名乱码
git config --global core.quotepath false

MAC上git diff/git log中文文件名乱码

配置了git config –global core.quotepath false后,git status中文文件名不乱码了,但git diff和git log中文文件名还是乱码,查了下
解决方案:
echo $LANG;
输出结果为空
执行export LANG=”zh_CN.UTF-8”命令,问题解决。
或者写到profile文件中,编辑~/.bash_profile,写入:
export LANG=”zh_CN.UTF-8” 保存后执行 source ~/.bash_profile使配置文件生效


credential.helper https免密登录

在 git 根目录执行 git config --global credential.helper store 命令,执行之后会在 ~/.gitconfig 文件中多加如下配置项:

[credential]
    helper = store

之后在 git 目录执行 git pull 命令,会提示输入账号密码。输完这一次以后就不再需要,并且会在根目录生成一个 .git-credentials 文件,之后 pull/push 代码都不再需要输入账号密码了

选项
默认所有都不缓存。 每一次连接都会询问你的用户名和密码。
cache 模式会将凭证存放在内存中一段时间。 密码永远不会被存储在磁盘中,并且在15分钟后从内存中清除。
store 模式会将凭证用明文的形式存放在磁盘中,并且永不过期。 这意味着除非你修改了你在 Git 服务器上的密码,否则你永远不需要再次输入你的凭证信息。 这种方式的缺点是你的密码是用明文的方式存放在你的 home 目录下。
osxkeychain 如果你使用的是 Mac,Git 还有一种 “osxkeychain” 模式,它会将凭证缓存到你系统用户的钥匙串中。 这种方式将凭证存放在磁盘中,并且永不过期,但是是被加密的,这种加密方式与存放 HTTPS 凭证以及 Safari 的自动填写是相同的。
如果你使用的是 Windows,你可以安装一个叫做 “Git Credential Manager for Windows” 的辅助工具。 这和上面说的 “osxkeychain” 十分类似,但是是使用 Windows Credential Store 来控制敏感信息。 可以在 https://github.com/Microsoft/Git-Credential-Manager-for-Windows 下载。

7.14 Git 工具 - 凭证存储
https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%87%AD%E8%AF%81%E5%AD%98%E5%82%A8


core.ignorecase文件名大小写敏感配置

git默认是文件名大小写不敏感的,即Java.txt 和java.txt会被当做是同一个文件,同样,如果只将Java.txt的文件名修改为java.txt,文件内容不动,git status是检测不出改动的。

如何修改文件名大小写?

1、设置git库为大小写敏感(不建议)
git config core.ignorecase false
用这种方法进行重命名,用git status就可以识别出修改了,但是不推荐用这种方式,因为在更新这种修改的时候会有麻烦。

2、修改文件名,在文件名中增加或减少字符来触发文件名修改
比如
ABC.java 先改为 ABCD.java 提交 git
ABCD.java 再改名为 abc.java 提交 git

3、使用git mv命令改文件名
使用git mv命令修改文件名(仅当core.ignorecase为true时可用)

$ git mv ABC.java Abc.java
$ git status
......
            renamed: ABC.java -> Abc.java

此时的状态是renamed,git commit即可。

如果使用Eclipse中的git插件进行仅涉及大小写的重命名,无论core.ignorecase设置为true还是false或者没有设置该项,修改之后均可正常提交,能识别出文件大小写重命名。


the following paths have collided

文件目录名大小写冲突,Mac 文件系统默认是大小写不敏感的,需要新建大小写敏感分区来解决,处理起来比较麻烦,建议改目录名来解决冲突
the following paths have collided (e.g. case-sensitive paths on a case-insensitive filesystem) and only one from the same colliding group is in the working tree:
components/User/index.js
components/user/index.js

https://stackoverflow.com/questions/63468346/case-sensitive-path-collisions-on-case-insensitive-file-system-when-i-do-git-clo


alias.co checkout 配置git别名简写

git config --global alias.co checkout 配置 git 别名 co 代替命令 checkout
这会在全局配置文件 ~/.gitconfig 中写入如下配置:

[alias]
    co = checkout

当然也可以直接编辑这个文件加入上面的配置项。

常用的简写命令还有:

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.st status

.gitignore 配置忽略文件

如果不想某些文件纳入git版本管理,可以在项目文件夹下创建一个名为 .gitignore 的文件,列出要忽略的文件模式。例如:

# 忽略所有以 .o 或 .a 结尾的编译中间文件
*.[oa]

# 忽略所有以波浪符(~)结尾的文件,文本编辑软件(比如Emacs)都用这样的文件名保存副本
*~

#忽略所有.svn目录(包括子目录中的)
.svn/

#忽略所有target目录(包括子目录中的)
target/

#忽略所有.idea目录(包括子目录中的)
.idea/

#忽略所有.iml文件
*.iml

.gitignore文件格式

文件 .gitignore 的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配。
  • 匹配模式可以以 / 结尾指定目录。
  • 默认都是递归匹配的(也就是会匹配所有子目录中的模式),可以以 / 开头防止递归。比如 target/ 忽略所有子目录中的 target 目录,但 /target/ 只忽略当前目录下的 target 目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号 ! 取反。比如 *.a 忽略所有以a结尾的文件后,还可以指定 !lib.a 继续跟踪 lib.a 文件

glob模式匹配

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
星号 * 匹配零个或多个任意字符;
[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
问号 ? 只匹配一个任意字符;
如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
使用两个星号 ** 表示匹配任意中间目录,比如 a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z 等。
一个较复杂的例子:

# no .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in the build/ directory
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory
doc/**/*.pdf

git status

git 文件的4种状态

git库所在的文件夹中的文件大致有4种状态

  • Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
  • Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改
  • Staged: 暂存状态. 执行 git commit 则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

git文件状态

git文件状态

git status 查看当前目录中文件状态

git status命令可显示当前目录中的文件处于什么状态,是否有新添加(未被跟踪的)的文件,如果刚clone下项目就执行git status,结果为:

$ git status
On branch master
nothing to commit, working directory clean

说明当前目录没有任何增删改。
向目录中添加一个文件commit.test,再次执行git status,结果为:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        commit.test

nothing added to commit but untracked files present (use "git add" to track)

显示有一个未跟踪的文件。

git status -s 状态简览

使用git status -sgit status --short可更清晰简单的查看文件状态:

$ git status -s
M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt
  • ??:新添加的未跟踪文件
  • A:新添加到暂存区中的文件
  • 右M:修改过的文件,但是还没放入暂存区
  • 左M:该文件被修改了并放入了暂存区

例如,上面的状态报告显示: README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区,lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区和工作区都有该文件被修改了的记录。


git add

git add files 跟踪新文件/暂存已修改文件

git add 命令将内容从工作目录添加到暂存区(或称为索引(index)区),以备下次提交。 当 git commit 命令执行时,默认情况下它只会检查暂存区域,因此 git add 是用来确定下一次提交时快照的样子的。

git add .,暂存当前目录下所有文件

跟踪新添加的文件commit.test
$ git add commit.test
暂存已修改的文件README.md
$ git add README.md

工作区/暂存区/版本库/远程库

工作区(Workspace):本地一个用于当前文件操作的工作区,就是当前工作目录。
暂存区(Stage/Index):一般存放在“.git/目录下”的index文件(.git/index)中,暂存区有时也叫作索引(index)。工作区的文件先被增加到这个区域里,再从这个区域提交到版本库,也就是工作区的快照。
版本库:工作区有一个隐藏目录.git/,这个不是工作区,而是Git的版本库。
远程版本库:托管再服务器上的仓库,可与本地代码库建立连接。

工作区 -> git add -> 暂存区 -> git commit -> 版本库 -> git push -> 远程库


git commit

git commit是提交到本地的git版本库,要想上传到GitHub远程仓库,还需要git push命令

每次准备提交前,先用git status看下,是不是都已暂存起来了,然后执行git commit命令,这种方式会启动文本编辑器(例如vim)以便输入本次提交的说明,编辑器会显示最后一次运行git status的输出,开头还有一空行,供你输入提交说明。

git commit -m “message” 带注释提交

此外,也可以使用git commit -m命令,将提交信息与命令放在同一行:
git commit -m "Git Bash commit test"

git commit -a 暂存并提交已跟踪文件

如果有文件没有被跟踪,此命令无法提交这些文件

git commit -am ‘message’ 暂存并提交已跟踪文件

如果有文件没有被跟踪,此命令无法提交这些文件

git commit –amend 改写提交

改变最近一次提交也许是最常见的重写历史的行为。对于你的最近一次提交,你经常想做两件基本事情:改变提交说明,或者改变你刚刚通过增加,改变,删除而记录的快照。

如果你只想修改最近一次提交说明,这非常简单:git commit –amend
这会把你带入文本编辑器,里面包含了你最近一次提交说明,供你修改。当你保存并退出编辑器,这个编辑器会写入一个新的提交,里面包含了那个说明,并且让它成为你的新的最近一次提交。

如果你完成提交后又想修改被提交的快照,增加或者修改其中的文件,可能因为你最初提交时,忘了添加一个新建的文件,这个过程基本上一样。你通过修改文件然后对其运行git add或对一个已被记录的文件运行git rm,随后的git commit –amend会获取你当前的暂存区并将它作为新提交对应的快照。


git stash 储藏

当要记录工作目录和索引的当前状态,但想要返回到干净的工作目录时,则使用git stash。

该命令保存本地修改,并恢复工作目录以匹配HEAD提交。这个命令所储藏的修改可以使用git stash list列出,使用git stash show进行检查,并使用git stash apply恢复(可能在不同的提交之上)。 默认情况下,储藏列表为“分支名称上的WIP”,但您可以在创建一个消息时在命令行上给出更具描述性的消息。

我们有时会遇到这样的情况,正在dev分支开发新功能,做到一半时有人过来反馈一个bug,让马上解决,但是新功能做到了一半你又不想提交,这时就可以使用git stash命令先把当前进度保存起来,然后切换到另一个分支去修改bug,修改完提交后,再切回dev分支,使用git stash pop来恢复之前的进度继续开发新功能。

使用git stash命令保存和恢复进度
https://blog.csdn.net/daguanjia11/article/details/73810577

git stash命令 - 易百教程
https://www.yiibai.com/git/git_stash.html

git stash 储藏进度

调用没有任何参数的git stash相当于git stash save
保存当前工作进度,会把暂存区和工作区的改动保存起来。执行完这个命令后,在运行git status命令,就会发现当前是一个干净的工作区,没有任何改动。

git stash save ‘message’ 带注释暂存

使用 git stash save 'message...' 可以添加一些注释

git stash -u 储藏未跟踪文件

默认情况下,git stash 只会储藏已经在索引中的文件。 如果指定 –include-untracked-u 标记,Git 也会储藏任何创建的未跟踪文件。
git stash -u|--include-untracked
储藏未跟踪文件:

git stash save -u “message” 带注释储藏未跟踪文件

git stash list 列出暂存的进度

注意:栈顶的stash@{0}是最近一次储藏的进度

$ git stash list
stash@{0}: On master: 增加配置文件
stash@{1}: On master: 增加log4j2日志框架

git stash show 查看stash文件列表及内容

git stash show 查看最新stash的文件列表
git stash show -p 在该命令后面添加 -p 或 –patch 可以查看特定stash的全部文件diff
git stash show -p stash@{1} 查看指定stash的全部文件diff

git stash apply stash@{1} 恢复储藏进度

git stash ( pop | apply ) [--index] [stash@{i}]
git stash apply,恢复最近的进度,如果不指定stash id,git认为是恢复最近的储藏进度stash@{0}
git stash apply stash@{2},恢复指定储藏进度,stash_id是通过git stash list命令得到的

git stash pop stash@{1} 恢复并删除储藏进度

git stash ( pop | apply ) [--index] [stash@{i}]
git stash pop,恢复最新的进度到工作区并删除进度。如果不指定stash id,git认为是恢复最近的储藏进度stash@{0}
git stash pop stash@{2},恢复指定储藏进度并删除进度,stash_id是通过git stash list命令得到的

git stash apply是恢复但不删除储藏栈上的进度,git stash pop恢复进度后会立即从储藏栈上删除刚恢复的进度。

Could not restore untracked files from stash entry

git stash pop 时报错如下

myapp/src/test/resources/application.yml already exists, no checkout
Could not restore untracked files from stash entry

原因:
好像是 git stash save -u 保存了 untracked 文件,但本地又新建了某个 untracked 文件,导致 pop 时报错,但其他不冲突的可以pop成功。

解决:
git checkout stash -- . 这个命令会强制覆盖本地变更

Why does git stash pop say that it could not restore untracked files from stash entry?
https://stackoverflow.com/questions/51275777/why-does-git-stash-pop-say-that-it-could-not-restore-untracked-files-from-stas

git stash apply/pop –index 恢复最新进度到工作区和暂存区

恢复最新的进度到工作区和暂存区。(尝试将原来暂存区的改动还恢复到暂存区)

git stash drop [stash_id]

删除一个存储的进度。如果不指定stash_id,则默认删除最新的存储进度。

$ git stash list
stash@{0}: On master: 增加配置文件
stash@{1}: On master: 增加log4j2日志框架
$ git stash drop 1
Dropped refs/stash@{1} (53c4ce9f1d8ccd962addefd27584844fb85946b1)

git stash clear 删除所有暂存进度

删除所有存储的进度。


git fsck 找回 drop 误删的 stash 信息并应用

git stash drop 误删的 stash 也可以召回并应用

1、显示已经 drop 的 stash 信息
git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk
2、应用已经 drop 的 stash
git stash apply <commit_hash>

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk
commit 863a717b7f22e1668d0afec70fcd2b9015868462
Merge: 28f9b82 a9c7848 c6026d0
Author: xxx <xx@xx.com>
Date:   Thu Oct 12 10:22:26 2023 +0800

    On f-1.4.x: push

How do I recover a dropped stash in Git?
https://stackoverflow.com/questions/89332/how-do-i-recover-a-dropped-stash-in-git


git rm

git rm 语法
git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>…

git rm file git仓库和本地同时删除

git rm file,从git仓库中删除文件,同时在本地工作目录删除文件

git rm -r 删除目录

git rm –r *,可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:

git rm -f file 删除暂存区的文件加-f

git rm -f <file>,如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

git rm –cached file git仓库删除但本地保留

git rm --cached file,把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 –cached 选项即可

Git 基本操作
http://www.runoob.com/git/git-basic-operations.html

删除git仓库中文件但本地保留

对于eclipse的maven项目,.classpath.project.settings/target/ 等文件和目录如果被提交到git仓库,并不方便其他项目成员使用,而且因为本地的环境变化,还会频繁要求提交这些文件的修改,所以这些文件不建议纳入git版本控制,通常.gitignore文件配置如下:

/target/
/.settings/
/.project
/.classpath

不过如果这些文件之前已经提交过,即已经被纳入git版本控制中,配置.gitignore也并不会将其从git版本控制中移除,这时需要在命令行中使用git rm --cached命令。Eclipse中EGit图形界面上没找到怎么操作。

我们想把文件从Git仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让Git继续跟踪。当你忘记添加.gitignore文件,不小心把一个很大的日志文件或一堆.a这样的编译生成文件添加到暂存区时,这一做法尤其有用。为达到这一目的,需要使用git rm命令的--cached选项。
打开Git Bash命令行,执行如下命令将这些文件从git仓库删除:

git rm -r --cached .settings/
git rm --cached .classpath
git rm --cached .project
git commit -m "remote .settings .classpath from git"

类似rm命令,删除文件夹时要带-r选项,最后别忘了还要git commit提交才能生效。


git clean

git clean -f 删除未跟踪文件

删除 untracked files
git clean -f
如果 clean.requireForce 配置项没有设为false,必须加-f参数来强制删除

git clean -fd 删除未跟踪文件及目录

连 untracked 的目录也一起删掉
git clean -fd

git clean -xfd 删除未跟踪及gitignore的文件及目录

连 gitignore 的untrack 文件/目录也一起删掉 (慎用,一般这个是用来删掉编译出来的 .o之类的文件用的)
git clean -xfd

git clean -nf 显示clean命令要删除的文件

在用上述 git clean 前,强烈建议加上 -n 参数来先看看会删掉哪些文件,防止重要文件被误删
加-n参数的clean命令不会真正删除。
git clean -nxfd
git clean -nf
git clean -nfd


git rebase

rebase 的作用简要概括为:可以对某一段线性提交历史进行编辑、删除、复制、粘贴;因此,合理使用 rebase 命令可以使我们的提交历史干净、简洁!

git rebase -i commit-id 列出commit供选择整理

git rebase -i [startpoint] [endpoint]
其中-i的意思是--interactive,即弹出交互式的界面让用户编辑完成合并操作
[startpoint] [endpoint]则指定了一个编辑区间,如果不指定[endpoint],则该区间的终点默认是当前分支HEAD所指向的commit(注:该区间指定的是一个前开后闭的区间)。

git rebase -i HEAD~3 列出最近3个commit供选择整理

从HEAD版本开始往过去数3个版本

git rebase 合并整理commit过程

在使用 Git 作为版本控制的时候,我们可能会由于各种各样的原因提交了许多临时的 commit,而这些 commit 拼接起来才是完整的任务。那么我们为了避免太多的 commit 而造成版本控制的混乱,通常我们推荐将这些 commit 合并成一个。

1、查看提交历史,git log
首先你要知道自己想合并的是哪几个提交,可以使用git log命令来查看提交历史,假如最近4条历史如下:
commit 3ca6ec340edc66df13423f36f52919dfa3……
commit 1b4056686d1b494a5c86757f9eaed844……
commit 53f244ac8730d33b353bee3b24210b07……
commit 3a4226b4a0b6fa68783b07f1cee7b688…….
历史记录是按照时间排序的,时间近的排在前面。

2、git rebase
想要合并1-3条,有两个方法

1)从HEAD版本开始往过去数3个版本
git rebase -i HEAD~3

2)指名要合并的版本之前的版本号
git rebase -i 3a4226b

其中,-i 的参数是不需要合并的 commit 的 hash 值
请注意3a4226b这个版本是不参与合并的,可以把它当做一个坐标

3、选取要合并的提交
执行了rebase命令之后,会弹出一个窗口,头几行如下:
pick 3ca6ec3 ‘注释…’
pick 1b40566 ‘注释…’
pick 53f244a ‘注释…’

  • pick:保留该commit(缩写:p)
  • reword:保留该commit,但我需要修改该commit的注释(缩写:r)
  • edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)这里和 reword 使用方法一样, 但 reword 在 :wq 后会直接让你进入修改编辑, edit :wq 后要再使用 git commit –amend 进入修改
  • squash:将该commit和前一个commit合并(缩写:s),会保留自身 commit message
  • fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
  • drop:我要丢弃该commit(缩写:d),不仅丢弃commit message,还是连改动一起丢弃,慎用
  • exec:执行shell命令(缩写:x)

比如:

pick  3ca6ec3   '注释...'
fixup 1b40566   '注释...'
fixup 53f244a   '注释...'

p 3ca6ec3   '注释...'
f 1b40566   '注释...'
f 53f244a   '注释...'

会将后两条commit删掉,只保留第一条

比如:
pick 3ca6ec3 ‘注释…’
squash 1b40566 ‘注释…’
squash 53f244a ‘注释…’
会将后两条commit信息合并到第一条末尾,然后将后两条commit删掉

输入wq保存并推出, 再次输入git log查看 commit 历史信息,你会发现这两个 commit 已经合并了。

如果有冲突,需要修改,修改的时候要注意,保留最新的历史,不然我们的修改就丢弃了。
修改以后要记得敲下面的命令:
git add .
git rebase –continue
如果你想放弃这次压缩的话,执行以下命令:
git rebase –abort

注意事项:如果这个过程中有操作错误,可以使用 git rebase –abort来撤销修改,回到没有开始操作合并之前的状态。

(Git)合并多个commit
https://segmentfault.com/a/1190000007748862

使用git rebase合并多次commit
https://juejin.im/entry/5ae9706d51882567327809d0


git log 查看提交历史

git log 倒序查看日志

默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的更新排在最上面。 这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。
例如:

commit c1110d276bac5fa13a6f4d5b97637a3d837e2a8f (HEAD -> master, origin/master)
Author: si.ma <xxxx@xxx.com>
Date:   Tue Feb 12 13:50:53 2019 +0800

    增加git文件状态图片

commit a3e874709087d3da8d87e2ae54f210ec1e7bd486
Author: si.ma <xxxx@xxx.com>
Date:   Wed Jan 30 20:49:24 2019 +0800

    增加导入Spring源码图

commit fd20cf4876dc74d3ad9b3f3b104bd336cc1277f9
Author: si.ma <xxxx@xxx.com>
Date:   Wed Jan 30 14:07:01 2019 +0800

    修改jvm图片

-n:只显示最近n条提交记录,如-2表示只显示最近2条记录
--pretty:指定使用不同于默认格式的方式展示提交历史

git log –pretty=oneline 单行显示

--pretty=oneline:将每个提交放在一行显示,查看的提交数很大时非常有用
--pretty=format:"%h - %an, %ar : %s":定制要显示的记录格式

git SHA-1 Hash值

在Git中,每个commit ID的信息(如cc127537978af35e2f502da7e8d22e340ed810e5)就是一个SHA-1 Hash值,它是对那个commit在Git仓库中的内容和头信息(Header)的一个校验和(checksum)。Linux kernel开创者和Git的开发者——Linus说,Git使用了SHA-1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。

在Git文件目录 .git/objects 中,根据commit的SHA-1值(40个十六进制数字)进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名

(<commit>|HEAD)^n(<commit>|HEAD)~n

(<commit>|HEAD)^n,指的是HEAD的第n个父提交(HEAD有多个父提交的情况下),如果HEAD有N个父提交,那么n取值必须小于等于N.
(<commit>|HEAD)~n,指的是HEAD的第n个祖先提交,用一个等式来说明就是:(<commit>|HEAD)~n = (<commit>|HEAD)^^^….(^的个数为n)

注意^~之间的区别,当父提交存在多个分支时,^n可以用来选择第n个分支,HEAD~n永远只选择第n级父节点的第一个分支。
例如:HEAD~i^2选择第i级父节点的第二个分支,以此类推;
所以:HEAD^=HEAD^1=HEAD~1;
如果没有分支,只有一条主线,则HEAD^^^=HEAD^1^1^1=HEAD~3,如果该级结点有第二个分支,则表示为:HEAD^^^2 = HEAD~2^2

^代表父提交,当一个提交有多个父提交时,可以通过在^后面跟上一个数字表示第几个父提交,^相当于^1
~n相当于连续的n个^
checkout只会移动HEAD指针,reset会改变HEAD的引用值。

What’s the difference between HEAD^ and HEAD~ in Git?
https://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git


git reflog 查看git操作记录

当你 (在一个仓库下) 工作时,Git 会在你每次修改了 HEAD 时悄悄地将改动记录下来。当你提交或修改分支时,reflog 就会更新。
只要HEAD发生变化,就可以通过reflog查看到。

例如:

c1110d2 (HEAD -> master, origin/master) HEAD@{0}: commit: 增加git文件状态图片
a3e8747 HEAD@{1}: commit: 增加导入Spring源码图
fd20cf4 HEAD@{2}: commit: 修改jvm图片
0784d51 HEAD@{3}: commit: 增加jvm图片
b874d92 HEAD@{4}: commit: 删除无用图片
05f2d06 HEAD@{5}: commit: 测试图片
8dee418 HEAD@{6}: commit: 增加vim键盘图vim-key.gif
c7bc92e HEAD@{7}: commit: 增加vim键盘图vim-key.png
b19471a HEAD@{8}: commit: 增加vim键盘图vim-key.png
cbf0eea HEAD@{9}: commit: 添加java面试准备-计算机基础相关图片
975ff4a HEAD@{10}: commit: 添加java面试准备-微服务相关图片
384576d HEAD@{11}: commit: 添加数据库面试笔记相关图片
0926943 HEAD@{12}: commit: 添加数据库面试笔记相关图片
8eda0d1 HEAD@{13}: commit: 添加java-面试-jvm相关图片
f4619f9 HEAD@{14}: commit: 添加java-面试-线程与并发相关图片
00f651a HEAD@{15}: commit: 添加java-集合框架相关图片
e28545d HEAD@{16}: commit: 添加java-准备-基础图片
bd40cf5 HEAD@{17}: commit: 添加图片
473800c HEAD@{18}: commit: 导入七牛云中的所有图片
0df8400 HEAD@{19}: commit: 添加图片
90760f4 HEAD@{20}: commit: 添加图片
19d9aeb HEAD@{21}: commit: 删除.DS_store
62da768 HEAD@{22}: commit (initial): 添加第一张图片

(1) HEAD@{n}表示HEAD指针在n次移动之前的情况
(2) 通过HEAD{n}语法可以引用存在reflog中的提交。
(3)
HEAD~n引用的是commit提交历史记录,沿着HEAD指针的父指针向上寻找。
HEAD{n}引用的是reflog中的提交记录,沿着当前HEAD的undo历史向上寻找。

git reflog和git log的区别

git reflog 可以查看所有分支的所有操作记录,包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录

git log是显示当前的HEAD和它的祖先的,递归是沿着当前指针的父亲,父亲的父亲,……,这样的原则。
git reflog根本不遍历HEAD的祖先。它是HEAD所指向的一个顺序的提交列表:它的undo历史。reflog并不是repo(仓库)的一部分,它单独存储,而且不包含在pushes,fetches或者clones里面,它纯属是本地的。
reflog可以很好地帮助你恢复你误操作的数据,例如你错误地reset了一个旧的提交,或者rebase,……,这个时候你可以使用reflog去查看在误操作之前的信息,并且使用git reset –hard 去恢复之前的状态。


git checkout

git checkout 命令用于切换分支或恢复工作树文件。git checkout 是git最常用的命令之一,同时也是一个很危险的命令,因为这条命令会重写工作区。

git checkout [branch] 切换分支

执行git checkout testing即可切换到testing分支

分支切换会改变你工作目录中的文件
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。

git checkout -b [branch] 新建并切换到分支

git checkout -b hotfix:新建并切换到hotfix分支,等于git branch hotfix命令加git checkout hotfix命令

git checkout – file 撤销修改

git checkout -- file 可以丢弃工作区的修改
例如git checkout -- readme.txt
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

  1. 一种是readme.txt自修改后还没有被放到暂存区(还没执行git add),现在,撤销修改就回到和版本库一模一样的状态;
  2. 一种是readme.txt已经添加到暂存区(已执行git add),又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。
注意:git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令(其实如果文件名和分支名不重复的话,直接 git checkout file 也可以)

git checkout – . 取消所有本地的修改

git checkout -- . 或写作 git checkout .,非常危险的一条命令,会取消所有本地的修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件。

撤销修改(廖雪峰)
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001374831943254ee90db11b13d4ba9a73b9047f4fb968d000


git checkout otherBranch files 合并其他分支的指定文件

git merge 合并的时候会将两个分支的内容完全合并,如果想合并一部分肯定是不行的。那怎么办?

如何从其他分支merge指定文件到当前分支,git checkout 是个合适的工具。
git checkout source_branch <path>...

例如:使用git checkout 将B分支上的系统消息功能添加到A分支上

# 当前在A分支上
$ git branch
  * A
    B
# 将B分支上的下列文件合并到A分支上
$ git checkout B message.html message.css message.js other.js

注意:在使用git checkout某文件到当前分支时,会将当前分支的对应文件强行覆盖

这里新增文件没问题,但是A分支上原有的other.js会被强行覆盖,如果A分支上的other.js有修改,在checkout的时候就会将other.js内容强行覆盖

git小技巧–如何从其他分支merge个别文件或文件夹
https://segmentfault.com/a/1190000008360855


git revert

git revert 撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。
git revert 撤销 某次操作,此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交。

git revert HEAD 撤销前一次commit

git revert HEAD^ 撤销前前一次commit

git revert commit_id 撤销指定commit

比如:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff 撤销指定的版本,撤销也会作为一次提交进行保存。
git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,
版本会递增,不影响之前提交的内容

git revert HEAD~2

下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。
git checkout hotfix
git revert HEAD~2

git revert 和 git reset的区别

  1. git revert 是用一次新的 commit 来回滚之前的 commit,git reset 是直接删除指定的 commit。
  2. 在回滚这一操作上看,效果差不多。但是在日后继续 merge 以前的老版本时有区别。因为 git revert 是用一次逆向的 commit“中和”之前的提交,因此日后合并老的 branch 时,导致这部分改变不会再次出现,但是 git reset 是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
  3. git reset 是把 HEAD 向后移动了一下,而 git revert 是 HEAD 继续前进,只是新的 commit 的内容和要 revert 的内容正好相反,能够抵消要被 revert 的内容。

git revert 用法
https://www.cnblogs.com/0616--ataozhijia/p/3709917.html

5.2 代码回滚:Reset、Checkout、Revert 的选择
https://github.com/geeeeeeeeek/git-recipes/wiki/5.2-%E4%BB%A3%E7%A0%81%E5%9B%9E%E6%BB%9A%EF%BC%9AReset%E3%80%81Checkout%E3%80%81Revert-%E7%9A%84%E9%80%89%E6%8B%A9


git reset 重设HEAD指针位置

git reset [--soft | --mixed | --hard | --merge | --keep] [<commit>]

本地临时切换到某commit-id看代码

1、找到要切换到 commit-id
git reflog 查看短 commit-id 或 git log --pretty=oneline 查看长 commit-id
或者从 GitHub, GitLab 等托管平台查看 commit_id

2、回退到某一个版本,即使是另一个分支的 commit-id 也没关系
git reset –hard commit_id

3、恢复代码:
git pull 从远端同步当前分支最新代码,会将之前 reset 回退覆盖,分支上就又是最新的代码了。

git reset commit-id 修改HEAD指针到指定commit-id

git reset commit_id 等于 git reset --mixed commit-id,将HEAD指针修改为指定commit-id,同时修改暂存区(索引)的内容为指定commit,但工作区内容不变。
commit-id可以根据 git refloggit log 获得,git log 得到的是 SHA-1 校验和,git reflog 记录的是操作记录对应的 SHA-1 校验和的前7位,都可以用在 git reset 参数中。
版本号无需写全,只有前7-8位就可以,Git会自动找到。

例如:

git reset --hard a00622f
git reset --hard a00622fb875d114947ed32303a36782aebe8daa4

git reset –soft commit-id

将 HEAD 引用指向给定提交。索引和工作目录的内容是不变的,在三个命令中对现有版本库状态改动最小。

git reset –mixed commit-id(默认)

这是 git reset 的默认模式,HEAD引用指向给定提交,并且索引内容(暂存区)也跟着改变,工作目录内容不变。这个命令会将索引变成你刚刚暂存该提交全部变化时的状态,会显示工作目录中有什么修改。

git reset –hard commit-id

HEAD 引用指向给定提交,索引内容和工作目录内容都会变给定提交时的状态。也就是在给定提交后所修改的内容都会丢失(新文件会被删除,不在工作目录中的文件恢复,未清除回收站的前提)。
git reset --hard,完成撤销,同时将代码恢复到 HEAD 对应的版本。
git reset --hard commit_id,完成撤销,同时将代码恢复到前一commit_id 对应的版本。

git reset HEAD 恢复暂存区到上次提交

git add 如果添加了错误文件,可以使用此命令使暂存区恢复到上次commit状态

git reset HEAD 如果后面什么都不跟的话 就是上一次add 里面的全部撤销了
git reset HEAD XXX/XXX/XXX.java 就是对某个文件进行撤销了

git reset HEAD~2 恢复暂存区到上上次提交

在提交层面上,reset 将一个分支的末端指向另一个提交。这可以用来移除当前分支的一些提交。比如,下面这两条命令让 hotfix 分支向后回退了两个提交。

git checkout hotfix
git reset HEAD~2

hotfix 分支末端的两个提交现在变成了悬挂提交。也就是说,下次 Git 执行垃圾回收的时候,这两个提交会被删除。换句话说,如果你想扔掉这两个提交,你可以这么做。

在Git中,用HEAD表示当前版本,也就是最新的提交,上一个版本就是 HEAD^,上上一个版本就是 HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成 HEAD~100

~^的区别

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A

A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

What’s the difference between HEAD^ and HEAD~ in Git?
https://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git

git reset –hard HEAD 恢复工作区和暂存区到上次提交

git reset –hard HEAD~2 恢复工作区和暂存区到上上次提交

撤销已commit但未push的修改

git log 找到上次git commit的 id,即commit后面那一长串
git reset --hard commit_id,完成撤销,同时将代码恢复到前一commit_id 对应的版本。
git reset commit_id,完成Commit命令的撤销,但是不对代码修改进行撤销,可以直接通过git commit 重新提交对本地代码的修改。

例如:
git reset --hard a1349f9b370a9890746a8792a441995751e364c3

拉错代码后撤销git pull

比如一不小心拉取了错误的远程分支来和本地分支合并,可以通过下面两种方法取消:
方法一:
git log
查看git commit日志,每个commit后有一串字符串,commit xxxxxxxxx,表示此commit的id
git reset --hard xxxxxxx
xxxxxxx就是自己想回退的commit对应的id
然后git status发现git pull的内容都没有了。

方法二:
git reflog 命令查看历史变更记录,例如:

6a8f898b (HEAD -> feature-0730, origin/feature-0730) HEAD@{0}: checkout: moving from dev-0730 to feature-0730
0879c18e (dev-0730) HEAD@{1}: reset: moving to 0879c18e
72d76bc7 (origin/dev-0730) HEAD@{2}: commit: 添加xxx
0879c18e (dev-0730) HEAD@{3}: commit: 添加xxxx
7142ef99 HEAD@{4}: commit: 添加xxxxxx
d5d7eced HEAD@{5}: checkout: moving from 3.2-so-fix to dev-0730
7c485a8a (3.2-so-fix) HEAD@{6}: commit: 新增xxxxx接口
a6784867 (3.2) HEAD@{7}: checkout: moving from 3.2 to 3.2-so-fix
a6784867 (3.2) HEAD@{8}: checkout: moving from 3.2 to 3.2
a6784867 (3.2) HEAD@{9}: checkout: moving from master to 3.2
1f6ba2fa (origin/master, origin/feature-0713, origin/HEAD, origin/0711-master-config, master) HEAD@{10}: pull: Fast-forward
b41faa56 HEAD@{11}: checkout: moving from dev-0730 to master
d5d7eced HEAD@{12}: commit: 新增xxx查询
43c3b5bb HEAD@{13}: commit: 新增xxxx查询
8ad4345e HEAD@{14}: commit (amend): 增加xxxx
3d8eb583 HEAD@{15}: commit: 更新xxxx配置
94238f4c HEAD@{16}: commit: 添加xxxxx配置
60152f92 HEAD@{17}: commit: 添加xxxx类
4b4bb804 HEAD@{18}: commit: 添加xxxxx代理类
3399c7d8 (feature-0730) HEAD@{19}: checkout: moving from feature-0730 to dev-0730
3399c7d8 (feature-0730) HEAD@{20}: checkout: moving from master to feature-0730
b41faa56 HEAD@{21}: pull: Fast-forward
9f15e746 (origin/0705-dev, feature-service) HEAD@{22}: checkout: moving from dev-xxxx to master
1347d4f4 (dev-xxxxxxxxx) HEAD@{23}: commit: xxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{24}: checkout: moving from dev-xxxxxxxxx to dev-xxxxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{25}: checkout: moving from dev-xxxxxxxxx to dev-xxxxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{26}: checkout: moving from feature-service to dev-xxxxxxxxx

此记录中不只有自己的commit,还有其他人在此分支上的操作。
git reset --hard xxxxx
xxxx是自己想回退的操作记录的id,即开头的一串字符串


git tag

git tag 命令用于创建,列出,删除或验证使用GPG签名的标签对象。同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签。人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。

git tag 列出所有标签

git tag 列出所有标签

git tag -l ‘v0.1.*’ 模式匹配搜索标签

git tag -l 'v0.1.*' 搜索符合模式的标签

git tag tag_name 打标签

git标签分为两种类型:轻量标签和附注标签。轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象。建议使用附注标签。
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。
轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。
而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。

创建轻量标签

git tag v0.1.2-light
创建轻量标签不需要传递参数,直接指定标签名称即可。

创建附注标签

git tag -a v0.1.2 -m "0.1.2版本"
创建附注标签时,参数-a即annotated的缩写,指定标签类型,后附标签名。参数-m指定标签说明,说明信息会保存在标签对象中。

给指定的commit打标签

给指定的commit打标签
打标签不必要在head之上,也可在之前的版本上打,这需要你知道某个提交对象的校验和(通过git log获取)。
git tag -a v0.1.1 9fbc3d0

git show tag_name 查看标签信息

查看标签信息
git show命令可以查看标签的版本信息:
git show v0.1.2

git checkout tag_name 切换到标签

换到标签
与切换分支命令相同,用 git checkout tagname

git tag -d tag_name 删除标签

删除标签
git tag -d v0.1.2
参数-d即delete的缩写,意为删除其后指定的标签。

git push origin -tags 推送标签到远程分支

标签发布
通常的git push不会将标签对象提交到git服务器,我们需要进行显式的操作:

将v0.1.2标签提交到git服务器
git push origin v0.1.2

将本地所有标签一次性提交到git服务器
git push origin –tags


git describe

git describe 打印最近一次 tag 的信息

输出格式
tag-提交次数-commitId

v1.0-2-g2414721
v1.0 是距离最近的 tag
2 表示自 tag v1.0 以来已有 2 次提交
g2414721 是 commit-id

在没有 tag 的 git 项目上执行 git describe 会报错,可以加参数 git describe --always 执行,没有 tag 时也可以输出 commitId


git branch

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
Git 的 “master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。

git branch [name] 创建分支

在master分支执行git branch testing即可创建一个名为testing的分支
注意:git branch 命令仅仅创建一个新分支,并不会自动切换到新分支中去。

错误:fatal: Not a valid object name: ‘master’.
git branch branch-name时出现此错误,原因是git init后还没有commit过,所以还没有真正建立master分支,先在master下git add .git commit一次,再创建分支即可

git branch 列出所有本地分支

git branch 不加任何参数,可列出所有本地分支。列出的分支前有*号的,表示当前检出的那一个分支。

git branch -r 列出所有远程分支

git branch -r 列出所有远程分支

git branch -a 列出所有远程和本地分支

git branch -a 列出所有分支,包括远程分支和本地分支

git branch -v 列出所有分支的最后一次提交

git branch -v 列出所有分支的最后一次提交

git branch -vv 列出本地分支及追踪的远程分支

develop                          3b3f817 [origin/develop] Merge branch 'feature-0322' into 'develop'
feature-0313-userSource          2321a5b 升级common包
feature-0330-campaign            3aa0b22 [origin/feature-0330-campaign] 更新xxxxxxxx
feature-0102-log                 1d236c6 elk多行日志采集
feature-0108-uuid                92c2771 升级common正式版
feature-0114-source              25b6d1a 升级common包,来源
feature-0123-userSourceType      b1e2496 [origin/feature-0123-userSourceType] 升级common正式包
feature-0220-coupon              2431993 [origin/feature-0220-coupon] Merge branch 'develop' into feature-0220-coupon
feature-0227-updatecommon        563147a 升级common包
feature-0321                     b8ec9d9 [origin/feature-0321] 无时间限制的活动创建时就是使用中状态
feature-0322                     efaa1a6 [origin/feature-0322] Merge branch 'feature-0322' of git.nevint.com:uds/user into feature-0322
feature-0913-jobcode             44a5eb3 [origin/feature-0913-jobcode] 升级uds-common-3.2.53,更新jobcode
feature-1006-identity            2a931ae merge release-1.0.3-0918 to user
feature-1010-identity            ad6b27e [origin/feature-1010-identity] 用户身份枚举修改兼容
feature-1017                     2eb10e0 [origin/feature-1017] 解决用户信息查不到nioCode的问题
feature-1027                     16de334 [origin/feature-1027] 去掉无用代码
feature-1107                     a2bfac2 去掉认证相关修改
feature-1201                     39522e0 升级common包
fix-user-identity                bde2fd3 redis过期时间设置修改
master                           a5a0980 [origin/master] venus auto merge

git branch –set-upstream-to 设置分支追踪关系

在某些场合,Git会自动在本地分支与远程分支之间,建立一种**追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动”追踪”origin/master分支。或者可以这么说,当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支。

Git也允许手动建立追踪关系:
git branch --set-upstream master origin/master
上面命令指定本地master分支追踪origin/master分支。
注意,此命令已废弃:fatal: the ‘–set-upstream’ option is no longer supported. Please use ‘–track’ or ‘–set-upstream-to’ instead.
git branch --set-upstream-to=origin/feature-0730 feature-0730
上面命令指定本地feature-0730分支追踪origin/feature-0730分支。

git branch -d branchname 删除本地分支

git branch -d 要求本地分支必须完全merge入其追踪的远程分支,或者已合入 HEAD
git branch -d feature-user-0830 删除本地 feature-user-0830 分支

git branch -D branchname 强制删除本地分支

git branch -D 等同于 git branch --delete --force
git branch -d 会检查本地分支是否已完全merge入其追踪的远程分支或者已合入HEAD,否则拒绝删除本地分支;而 git branch -D 会强制删除本地分支。

批量删除本地分支

git branch |grep 'feature-user' |xargs git branch -D, 强制删除所有名称包含feature-user的本地分支。

git branch -m/-M oldName newName 重命名本地分支

本地分支重命名(还没有推送到远程)
git branch -m oldName newName

如果 newName 存在,必须使用 -M 来强制重命名:
git branch -M oldName newName

可以直接在当前分支重命名当前分支,oldName 不填的话默认是当前分支,
例如,master分支改名为 main 分支:
git branch -M main

重命名远程分支

若分支已推送到远程,想重命名怎么办?
远程分支重命名 (已经推送远程-假设本地分支和远程对应分支名称相同)

  1. 重命名远程分支对应的本地分支
    git branch -m oldName newName

  2. 删除远程分支
    git push –delete origin oldName

  3. 上传新命名的本地分支
    git push origin newName

4.把修改后的本地分支与远程分支关联
git branch –set-upstream-to origin/newName


git merge

git merge branch_name 将分支 branch_name 合并到当前分支。

git merge dev 将dev合入当前分支

只需要 checkout 到你想合并入的分支,然后运行 git merge 命令

假设从主干 master 拉出一个分支 dev,开发完后想合并到主干,首先检出(切换)到master:
git checkout master
然后执行:
git merge dev

git merge dev –ff fast-forward不创建新commit

--ff 如果是 fast-forward 合并则不需要创建新的 commit,这是默认行为。

git merge dev –no-ff 即使fast-forward也创建commit

--no-ff 即使是 fast-forward 合并也创建一个 commit

--no-commit 告诉git合并后不要自动提交。当您想要对合并进行进一步更改时,可以使用此选项,或者想要自己编写合并提交消息。

fatal: refusing to merge unrelated histories

原因:
本地新建一个项目后初始化 git 环境, 添加了一个 .gitignore 文件。
GitHub 远程也新建一个项目,有一条 commit 记录。
然后把本地项目和远程仓库关联上,但本地和远程各有一次 commit 历史记录,且互相无关,git 默认不允许有这种记录的进行merge,导致无法合并。

解决:
在你操作命令后面加 --allow-unrelated-histories
例如: git merge feature-11 --allow-unrelated-histories
如果你是 git pull 或者 git push 报 fatal: refusing to merge unrelated histories
同理:git pull origin master --allow-unrelated-histories

冲突处理

在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们,就会产生冲突。
使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。
冲突示例:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。

在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。


git diff

git比较两个分支的文件的差异

git diff branch1 branch2 显示出所有有差异的文件的详细差异

git diff branch1 branch2 –stat 列出2个分支有差异的文件列表

git diff branch1 branch2 文件名(带路径) 显示指定文件的详细差异

git diff tag1 tag2 两个标签间做diff

git diff stash@{0} 和stash对比

或者先 git stash list 列出 stash 列表
再 git diff

当前工作目录和stash对比

需要将当前内容临时commit,对比之后再恢复
git add .
git commit -m “temp”
git diff stash@{0}
git reset HEAD~


git clone

git clone remote_url directory 克隆远程仓库到本地

命令格式:
git clone <远程仓库地址> <本地目录名>

git clone 实际上是一个封装了其他几个命令的命令。 它创建了一个新目录,切换到新的目录,然后 git init 来初始化一个空的 Git 仓库, 然后为你指定的 URL 添加一个(默认名称为 origin 的)远程仓库(git remote add),再针对远程仓库执行 git fetch,最后通过 git checkout 将远程仓库的最新提交检出到本地的工作目录。

git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等。

进入要存放项目的目录,例如D:\Files\Git,Git Bash执行:
git clone https://github.com/kk/kk.github.io

$ git clone https://github.com/kk/kk.github.io.git
Cloning into 'kk.github.io'...
remote: Counting objects: 18, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 18 (delta 1), reused 0 (delta 0), pack-reused 9
Unpacking objects: 100% (18/18), done.
Checking connectivity... done.

git clone –depth=1 浅克隆

git clone --depth=1 只克隆 HEAD 最新 commit

浅克隆与正常克隆的区别:

  • 使用了 –depth 克隆的仓库就是一个浅克隆的仓库,并不完整,只包含远程仓库的 HEAD 分支。
  • 没有远程仓库的 tags,执行 git describe 命令会报错
  • 不 fetch 子仓库(submodules)

git remote

git remote 列出所有远程仓库简写

git remote 命令会列出已配置的每个远程仓库的简写

git remote -v 列出所有远程仓库url

git remote -v 命令会显示远程仓库的简写与对应的URL:

$ git remote -v
origin  https://github.com/kk/kk.github.io.git (fetch)
origin  https://github.com/kk/kk.github.io.git (push)

git remote show shortname 查看远程仓库详情

它会列出远程仓库的 URL 与跟踪分支的信息。 这些信息非常有用,它告诉你正处于 master 分支,并且如果运行 git pull,就会抓取所有的远程引用,然后将远程 master 分支合并到本地 master 分支。 它也会列出拉取到的所有远程引用。
例如:

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/kk/kk.github.io.git
  Push  URL: https://github.com/kk/kk.github.io.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':

git remote add shortname url 添加远程仓库

如果你使用git clone命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以origin为简写。
执行命令git remote add shortname url来添加远程仓库,其中shortname为自定义的远程仓库的简写(别名)
例如:

git remote add github git@github.com:masikkk/blog.git
git push -u origin master

git remote rename old new 重命名远程仓库简写名

远程仓库的移除与重命名
如果想要重命名引用的名字可以运行 git remote rename 去修改一个远程仓库的简写名。

例如,想要将 pb 重命名为 paul,可以用 git remote rename 这样做:
git remote rename pb paul
值得注意的是这同样也会修改你的远程分支名字。 那些过去引用 pb/master 的现在会引用 paul/master。

git remote rm shortname 删除远程仓库

比如想要给项目换个远程仓库,可以先删除当前的origin仓库,再添加新远程仓库
git remote rm origin 删除克隆时自动添加的origin远程仓库

github项目重命名流程

1、在 GitHub 页面上 rename 项目名,在 Settings 中第一个设置项就是重命名,重命名后,之前的项目链接还是可以正常访问,GitHub会自动做重定向。
2、本地 git remote rm origin 删除 origin 远程仓库,git remote add origin git@github.com:masikkk/algorithms.git 重新关联新的远程仓库 地址。
3、本地修改项目文件夹名

git remote,易百教程
http://www.yiibai.com/git/git_remote.html


git push

git push origin local:remote 推送到远程仓库

命令格式:
git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull<远程分支>:<本地分支>,而git push<本地分支>:<远程分支>

git push origin local 推送或创建同名远程分支

如果省略远程分支名,则表示将本地分支推送到与之存在“追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
git push origin master
上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

git push origin 推送到追踪的远程分支

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略:
git push origin
上面命令表示,将当前分支推送到origin主机的对应分支。

git push 推送到当前分支的默认远程分支

如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push
git push -u origin master
上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。
git push --all origin
上面命令表示,将所有本地分支都推送到origin主机。

如何查看当前分支的默认远程分支是哪个?

例如:
git push -u origin master
这条命令将origin/master 设置为默认被推送的分支。以后直接git push就可以了。
但是过段时间忘了。我想查看。命令是什么呢?
答:
这些设置保存在本地config里,用以下命令查看:
git config --local -l
相关条条目:

branch.master.remote=origin

表示master分支默认跟踪的远程主机是origin

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用–force选项。
git push --force origin
上面命令使用–force选项,结果导致在远程主机产生一个”非直进式”的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用–force选项。

git push –set-upstream/-u origin [远程分支名] 推送时设置追踪关系

git push --set-upstream origin masikkk-dev-0730
等于
git push -u origin masikkk-dev-0730
将本地分支推送到同名远程分支,同时设置追踪关系

push到GitHub

执行git push origin master命令后会提示输入username,但这里要输入邮箱,否则push不成功,如下:
Username for 'https://github.com': 1989@163.com
输入邮箱后弹出输入密码的对话框,输入GitHub登录密码,然后push成功。

$ git push origin master
Username for 'https://github.com': 1989@163.com
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 898 bytes | 0 bytes/s, done.
Total 9 (delta 2), reused 0 (delta 0)
To https://github.com/kk/kk.github.io.git
   4e5e46e..e81605d  master -> master

在GitHub上新建分支

  1. git clone 克隆远程仓库到本地
  2. git branch newbranch 新建分支
  3. git push origin newbranch 提交新分支到远程仓库

git push origin –delete [远程分支名] 删除远程分支

运行带有--delete选项的git push命令来删除一个远程分支。
例如:如果想要从服务器上删除serverfix分支,运行下面的命令:
git push origin --delete serverfix

或者在git push命令中省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。
$ git push origin :master
等同于
$ git push origin --delete master
上面命令表示删除origin主机的master分支。

注意:如果此远程分支为项目的默认分支,无法删除,会提示:
! [remote rejected] hexo_branch (refusing to delete the current branch: refs/heads/hexo_branch)
需要登录GitHub(或其他Git托管网站),将项目的默认分支修改为其他分支。

git push,易百教程
http://www.yiibai.com/git/git_push.html


git fetch

拉取远程分支并创建本地分支

使用如下git命令查看所有远程分支:
git branch -r

拉取远程分支并创建本地分支
方法一
使用如下命令:
git checkout -b 本地分支名x origin/远程分支名x
使用该方式会在本地新建分支x,并自动切换到该本地分支x。
采用此种方法建立的本地分支会和远程分支建立映射关系。

方式二
使用如下命令:
git fetch origin 远程分支名x:本地分支名x
如果本地不存在分支x,使用该方式会在本地新建分支x,但是不会自动切换到该本地分支x,需要手动checkout。
采用此种方法建立的本地分支不会和远程分支建立映射关系。

强制远程分支覆盖本地分支

git fetch --all  # fetch所有分支上的内容
git reset --hard origin/master # 重置本地分支,master改为对应分支名
git pull # 拉取远程分支并与本地分支合并

git pull

git pull origin remote:local 拉取远程分支并与本地合并

命令格式:
git pull <远程主机名> <远程分支名>:<本地分支名>

例如,取回origin主机的next分支,与本地的master分支合并:
git pull origin next:master

git pull origin remote 拉取远程分支与当前本地分支合并

如果远程分支是与当前分支合并,则冒号后面的部分可以省略:
git pull origin master
表示取回origin/master分支,再与当前分支合并。实质上,git pull等同于先做git fetch,再做git merge
git fetch origin
git merge origin/master

git pull origin 拉取有追踪关系的远程分支并合并

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名:
git pull origin
上面命令表示,本地的当前分支自动与对应的origin主机”追踪分支”(remote-tracking branch)进行合并。

git pull 拉取唯一追踪的远程分支并合并

如果当前分支只有一个追踪分支,连远程主机名都可以省略:
git pull
上面命令表示,当前分支自动与唯一一个追踪分支进行合并。

git pull,易百教程
http://www.yiibai.com/git/git_pull.html


列出远程分支git branch -a

git branch -a
加上-a参数可以查看远程分支,远程分支会用红色表示出来(如果你开了颜色支持的话)

移除远程仓库

如果不想Git与现在的远程仓库关联了,可以执行:
git remote rm origin
即删除clone时默认添加的远程仓库origin


Git 子模块

git clone –recursive 克隆带有子模块的远程仓库

如果某个项目需要包含并使用另一个项目,例如第三方库,需要使用git clone --recursive命令进行递归clone。
如果只是在主项目中git clone,虽然会生成子模块的目录,但其中还没有任何文件,需要再次执行git submodule initgit submodule update命令来初始化和拉取子模块数据。而git clone --recursive命令则可以一次性自动初始化并更新仓库中的每一个子模块。
例如:
$ git clone --recursive https://github.com/chaconinc/MainProject

错误:git clone --recursive时提示fatal: reference isn’t a tree

fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'cpy-leveldb'

原因是我们本地对子模块进行了修改但是并没有推送到子模块的远程仓库,然后在主项目中提交了一个指向那个非公开状态的指针然后推送远程仓库。当在其他地方进行git submodule update或迭代clone时,那个子模块系统会找不到所引用的提交。


git submodule add 添加子模块

将一个已存在的 Git 仓库clone下来并添加为正在工作的仓库的子模块。 你可以通过在git submodule add命令后面加上想要跟踪的项目 URL 来添加新的子模块。

$ git submodule add https://github.com/wzpan/hexo-theme-freemind.git themes/freemind
Cloning into 'themes/freemind'...
remote: Counting objects: 2136, done.
remote: Total 2136 (delta 0), reused 0 (delta 0), pack-reused 2136
Receiving objects: 100% (2136/2136), 35.03 MiB | 869.00 KiB/s, done.
Resolving deltas: 100% (986/986), done.
Checking connectivity... done.

通过ls -a命令可以看到主项目下多了一个.gitmodules隐藏文件,内容为:

[submodule "themes/freemind"]
        path = themes/freemind
        url = https://github.com/wzpan/hexo-theme-freemind.git

如果有多个子模块,该文件中就会有多条记录。


git submodule update –remote 更新子模块

如果项目中的子项目(例如第三方库)的远程仓库有了更新,我们可以进入某个子项目目录,执行git pull来更新该子项目,或者直接在主项目目录中执行git submodule update --remote [submodule-name]来更新指定子项目,如果直接输入git submodule update --remote,会尝试更新所有子项目。


提交带有子模块的项目

与普通提交无异,还是在主目录中通过git add .git commit -m 提交,如果要提交到自己主项目的远程仓库,还是git push命令。如果使用GitHub的话,提交后上GitHub页面查看,会发现子项目是直接链接到第三方库的GitHub页面的。

但是如果子模块不是自己的项目,是无法push到原作者的远程仓库的,这点一定要注意。


删除子模块

  • 删除submodule目录的.git隐藏文件夹。
  • 修改.gitmodules文件,去掉submodule子模块,如果只有这一个子模块的话,直接删除.gitmodules文件
  • 修改.git\config文件,去掉submodule子模块;
  • 删除.git\modules\submodule目录;
  • git rm --cached submodule,使submodule目录脱离Git版本控制

如果不需要submodule子模块了,直接删除物理文件夹;如果是想把submodule当做普通文件夹继续进行Git版本管理,再执行git add .将其纳入Git版本控制。


上一篇 Jira及Confluence使用笔记

下一篇 Hexo博客(04)free2mind主题配置

阅读
评论
21.3k
阅读预计86分钟
创建日期 2016-04-03
修改日期 2023-11-10
类别
目录
  1. 其他
    1. git统计脚本
      1. 所有提交者及其次数
      2. 统计某个人的代码提交行数
      3. 统计某时间范围内的代码提交行数
      4. 统计每个人的代码增删行数
    2. git lfs 大文件
      1. This repository is over its data quota
    3. GitLab关联JIRA的issue
    4. 批量更新当前目录下的git项目shell脚本
    5. git存储原理
      1. git count-objects 查看git磁盘占用
      2. git filter-branch 对所有分支进行过滤操作
      3. 彻底删除文件避免磁盘占用
  2. git init
    1. 重建现有仓库
  3. git config
    1. git config -l 列出所有git配置
    2. git配置文件.gitconfig
      1. /etc/gitconfig 系统配置–system
      2. ~/.gitconfig 用户配–global
      3. .git/config 项目配置–local
    3. user.name/user.email 用户信息配置
    4. 不同项目配置不同用户信息
    5. core.autocrlf 换行符自动转换
    6. core.safecrlf 换行符检查
    7. core.quotepath 中文文件名乱码
      1. MAC上git diff/git log中文文件名乱码
    8. credential.helper https免密登录
    9. core.ignorecase文件名大小写敏感配置
      1. 如何修改文件名大小写?
    10. the following paths have collided
    11. alias.co checkout 配置git别名简写
  4. .gitignore 配置忽略文件
    1. .gitignore文件格式
    2. glob模式匹配
  5. git status
    1. git 文件的4种状态
    2. git status 查看当前目录中文件状态
    3. git status -s 状态简览
  6. git add
    1. git add files 跟踪新文件/暂存已修改文件
    2. 工作区/暂存区/版本库/远程库
  7. git commit
    1. git commit -m “message” 带注释提交
    2. git commit -a 暂存并提交已跟踪文件
    3. git commit -am ‘message’ 暂存并提交已跟踪文件
    4. git commit –amend 改写提交
  8. git stash 储藏
    1. git stash 储藏进度
    2. git stash save ‘message’ 带注释暂存
    3. git stash -u 储藏未跟踪文件
    4. git stash save -u “message” 带注释储藏未跟踪文件
    5. git stash list 列出暂存的进度
    6. git stash show 查看stash文件列表及内容
    7. git stash apply stash@{1} 恢复储藏进度
    8. git stash pop stash@{1} 恢复并删除储藏进度
      1. Could not restore untracked files from stash entry
    9. git stash apply/pop –index 恢复最新进度到工作区和暂存区
    10. git stash drop [stash_id]
    11. git stash clear 删除所有暂存进度
    12. git fsck 找回 drop 误删的 stash 信息并应用
  9. git rm
    1. git rm file git仓库和本地同时删除
    2. git rm -r 删除目录
    3. git rm -f file 删除暂存区的文件加-f
    4. git rm –cached file git仓库删除但本地保留
    5. 删除git仓库中文件但本地保留
  10. git clean
    1. git clean -f 删除未跟踪文件
    2. git clean -fd 删除未跟踪文件及目录
    3. git clean -xfd 删除未跟踪及gitignore的文件及目录
    4. git clean -nf 显示clean命令要删除的文件
  11. git rebase
    1. git rebase -i commit-id 列出commit供选择整理
    2. git rebase -i HEAD~3 列出最近3个commit供选择整理
    3. git rebase 合并整理commit过程
  12. git log 查看提交历史
    1. git log 倒序查看日志
    2. git log –pretty=oneline 单行显示
    3. git SHA-1 Hash值
    4. (<commit>|HEAD)^n和(<commit>|HEAD)~n
  13. git reflog 查看git操作记录
    1. git reflog和git log的区别
  14. git checkout
    1. git checkout [branch] 切换分支
    2. git checkout -b [branch] 新建并切换到分支
    3. git checkout – file 撤销修改
    4. git checkout – . 取消所有本地的修改
    5. git checkout otherBranch files 合并其他分支的指定文件
  15. git revert
    1. git revert HEAD 撤销前一次commit
    2. git revert HEAD^ 撤销前前一次commit
    3. git revert commit_id 撤销指定commit
    4. git revert HEAD~2
    5. git revert 和 git reset的区别
  16. git reset 重设HEAD指针位置
    1. 本地临时切换到某commit-id看代码
    2. git reset commit-id 修改HEAD指针到指定commit-id
      1. git reset –soft commit-id
      2. git reset –mixed commit-id(默认)
      3. git reset –hard commit-id
    3. git reset HEAD 恢复暂存区到上次提交
    4. git reset HEAD~2 恢复暂存区到上上次提交
      1. ~和^的区别
    5. git reset –hard HEAD 恢复工作区和暂存区到上次提交
    6. git reset –hard HEAD~2 恢复工作区和暂存区到上上次提交
    7. 撤销已commit但未push的修改
    8. 拉错代码后撤销git pull
  17. git tag
    1. git tag 列出所有标签
    2. git tag -l ‘v0.1.*’ 模式匹配搜索标签
    3. git tag tag_name 打标签
      1. 创建轻量标签
      2. 创建附注标签
      3. 给指定的commit打标签
    4. git show tag_name 查看标签信息
    5. git checkout tag_name 切换到标签
    6. git tag -d tag_name 删除标签
    7. git push origin -tags 推送标签到远程分支
  18. git describe
  19. git branch
    1. git branch [name] 创建分支
    2. git branch 列出所有本地分支
    3. git branch -r 列出所有远程分支
    4. git branch -a 列出所有远程和本地分支
    5. git branch -v 列出所有分支的最后一次提交
    6. git branch -vv 列出本地分支及追踪的远程分支
    7. git branch –set-upstream-to 设置分支追踪关系
    8. git branch -d branchname 删除本地分支
    9. git branch -D branchname 强制删除本地分支
    10. 批量删除本地分支
    11. git branch -m/-M oldName newName 重命名本地分支
    12. 重命名远程分支
  20. git merge
    1. git merge dev 将dev合入当前分支
    2. git merge dev –ff fast-forward不创建新commit
    3. git merge dev –no-ff 即使fast-forward也创建commit
    4. fatal: refusing to merge unrelated histories
    5. 冲突处理
  21. git diff
    1. git diff branch1 branch2 显示出所有有差异的文件的详细差异
    2. git diff branch1 branch2 –stat 列出2个分支有差异的文件列表
    3. git diff branch1 branch2 文件名(带路径) 显示指定文件的详细差异
    4. git diff tag1 tag2 两个标签间做diff
    5. git diff stash@{0} 和stash对比
      1. 当前工作目录和stash对比
  22. git clone
    1. git clone remote_url directory 克隆远程仓库到本地
    2. git clone –depth=1 浅克隆
  23. git remote
    1. git remote 列出所有远程仓库简写
    2. git remote -v 列出所有远程仓库url
    3. git remote show shortname 查看远程仓库详情
    4. git remote add shortname url 添加远程仓库
    5. git remote rename old new 重命名远程仓库简写名
    6. git remote rm shortname 删除远程仓库
    7. github项目重命名流程
  24. git push
    1. git push origin local:remote 推送到远程仓库
    2. git push origin local 推送或创建同名远程分支
    3. git push origin 推送到追踪的远程分支
    4. git push 推送到当前分支的默认远程分支
      1. 如何查看当前分支的默认远程分支是哪个?
    5. git push –set-upstream/-u origin [远程分支名] 推送时设置追踪关系
    6. push到GitHub
    7. 在GitHub上新建分支
    8. git push origin –delete [远程分支名] 删除远程分支
  25. git fetch
    1. 拉取远程分支并创建本地分支
    2. 强制远程分支覆盖本地分支
  26. git pull
    1. git pull origin remote:local 拉取远程分支并与本地合并
    2. git pull origin remote 拉取远程分支与当前本地分支合并
    3. git pull origin 拉取有追踪关系的远程分支并合并
    4. git pull 拉取唯一追踪的远程分支并合并
    5. 列出远程分支git branch -a
    6. 移除远程仓库
  27. Git 子模块
    1. git clone –recursive 克隆带有子模块的远程仓库
    2. git submodule add 添加子模块
    3. git submodule update –remote 更新子模块
    4. 提交带有子模块的项目
    5. 删除子模块

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论