Git 笔记

本贴最后更新于 2002 天前,其中的信息可能已经东海扬尘

免费和开源

Git 是一个使用 GNU GPL2.0 协议的开源软件。Git 选择 GPLv2 来确保你可以自由的分享和改造自由软件,而且能确保使用它的任何用户都是自由免费的。
然而,我们确实也保留了 “Git” 和 logos 避免争议。欲知详情请看我们的商标政策。

1.常用命令

git remote add origin git@github.com:lbb4511/cand.git // 添加远程
git push -u origin master // 提交
git push -f origin master // 强制推送
git submodule add git://github.com/lbb4511/rack.git rack // 添加子模块
git fetch --all && git reset --hard origin/master && git pull // 强制覆盖本地
git status // 查看
git remote rm origin && git remote add origin https://github.com/lbb4511/doc.git // 换远程仓库

git checkout -b dev // 从已有的分支创建新的分支(如从master分支),创建一个dev分支
git branch --set-upstream-to=origin/dev  // 建立本地到上游(远端)仓的链接 --这样代码才能提交上去
git branch --unset-upstream master // 取消对master的跟踪
git push origin dev // 提交该分支到远程仓库

2. 安装

  • Linux
# Fedora 上的 yum:
$ sudo yum install git
# Debian 上的 apt-get:
$ sudo apt-get install git

Git 官方网站上有在各种 Unix 风格的系统上安装步骤

# 版本查询
git --version

3. Git 环境设置

初次运行 Git 前的配置 git config

git config -e # 当前Git存储库
git config -e --global # 全局设置
git config -e --system # 系统设置
  • Git 的三个配置文件
    • 版本库级别的配置文件(/.git/config)
    • 全局配置文件(用户主目录下)
    • 系统级配置文件(/etc 目录下)
      这个命令的作用是打开相应的配置文件,并且进行编辑。其中版本库级别的配置文件的优先级最高,全局配置文件次之,系统级别配置文件最低。Git 配置文件采用的是 INI 文件格式。
git config <section>.<key> # 读取和更改INI配置文件的内容
git config <section>.<key> <value> # 修改INI配置文件中某个配置的键值
  • 设置用户名
git config --global user.name "Your Name"
  • 设置电子邮件 ID
git config --global user.email "email@example.com"
  • 查看个人信息
git config --list
  • 避免 PULLING 提交合并
git config --global branch.autosetuprebase always
  • 颜色高亮
    下面的命令使颜色突出显示在控制台的 Git。
git config --global color.ui true
git config --global color.status auto
git config --global color.branch auto
  • 设置默认编辑器
git config --global core.editor vim
  • 设置 git 命令的别名
git config --global alias.ci commit
git config --global alias.co checkout
  • 设置默认的合并工具
git config --global merge.tool vimdiff
  • 删除 git 全局配置文件中的用户名
git config --unset --global user.name
git config --unset --global user.email
  • 远程仓库设置
    • 生成公共/私有 RSA 密钥对
ssh-keygen -t rsa -C "youremail@example.com"
cat ~/.ssh/id_rsa.pub
#github.com验证
ssh -T git@github.com

一个是私有的 id_rsa,另一个是公共 id_rsa.pub

  • 远程链接

Add Key

4. 仓库

  • 创建本地版本库
mkdir gittest
cd learngit
pwd
git init

添加远程 Git 仓库

git remote add [origin] [SSH] # 关联一个远程库,添加远程[SSH]的[origin]分支
git push origin master # 第一次推送master分支的所有内容,不能为空

此后,每次本地提交后,只要有必要,就可以使用命令 git push origin master 推送最新修改到 master 分支;
例:git remote add origin git@github.com:lbb4511/Story.git
github 上传时出现 error: src refspec master does not match any 解决办法 主要是没有要同步的文件

克隆远程 Git 仓库

git clone <repository> <directory> # 将repository指向的版本库创建一个克隆到directory目录中。目录directory相当于克隆版本库的工作区,文件都会检出,版本库位于工作区下得.git目录中。
git clone --bare <repository> <directory.git>
git clone --mirror <repository> <directory.git>
# 上面的两种克隆版本都不包含工作区,直接就是版本库的内容,这样的版本库称为裸版本库。
git clone SSH # 简写

例:git clone git@github.com:github/hub.git

  • 合并两个仓库
    • 远端的服务器上下载数据(git pull)
git pull # 从远端的服务器上下载数据,从而实现同步更新。要获取的远程版本库的URL地址由remote.<remote>.url提供。

推送本地库到远程仓库(git push)

git push <remote> [branch] # 就会将你的 [branch] 分支推送成为 [alias] 远端上的 [branch] 分支
要推送的远程版本号的URL地址由remote.<remote>.pushurl给出,如果没有配置,则使用remote.<remote>.url配置的URL地址。

提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支。
提示:再次推送前,先与远程变更合并(如 'git pull ...')。详见
提示:'git push --help' 中的 'Note about fast-forwards' 小节。
引起这个问题是远程仓库和本地不同步引起的
解决方案:需要先获取远端更新并与本地合并,再 git push 具体操作如下:

git remote -v # 查看远程仓库
git remote add [origin] [SSH] # 添加远程[SSH]的[origin]分支
git fetch origin # 获取远程更新
git merge origin/master # 把更新的内容合并到本地分支
  1. 从已有的分支创建新的分支(如从 master 分支),创建一个 dev 分支

git checkout -b dev

  1. 创建完可以查看一下,分支已经切换到 dev
git branch

	* dev

	master
  1. 提交该分支到远程仓库

    git push origin dev

  2. 建立本地到上游(远端)仓的链接 --这样代码才能提交上去 git branch --set-upstream-to=origin/dev

  3. 取消对 master 的跟踪 git branch --unset-upstream master

git 创建分支提交远程分支 - oppotvr
https://my.oschina.net/u/219482/blog/285584

以下两个应该是同一个意思,=upstream : 上游码流的意思
git branch --set-upstream-to=master
git branch --set-upstream-to=original/master

git help branch
git branch [--set-upstream | --track | --no-track][-l] [-f] []
git branch (--set-upstream-to= | -u ) []
git branch --unset-upstream []

git branch --set-upstream-to=original/master new
git branch --set-upstream debug origin/debug //其中 debug 为创建的分支

参考合并两个 git 仓库

合并两个 git 仓库

# 创建仓库1
mkdir repo1
cd repo1
git init
echo "repo1.txt" > repo1.txt
git add repo1.txt
git ci -m "init repo1"
# 创建仓库2
mkdir repo2
cd repo2
git init
echo "repo2.txt" > repo2.txt
git add repo2.txt
git ci -m "init repo2"
git remote add other ../repo1/ # 将repo1作为远程仓库,添加到repo2中,设置别名为other
git fetch other # 从repo1仓库中抓取数据到本仓库
git checkout -b repo1 other/master # 将repo1仓库抓去的master分支作为新分支checkout到本地,新分支名设定为repo1
git checkout master # 切换回repo2的master分支
git merge repo1 # 将repo1合并入master分支

分支和合并

  • Git 跟其他版本控制系统最大的优势就在于其高级的分支模型。
  • Git 允许而且鼓励 你在本地使用多个完全独立的分支。这些分支的创建,合并和删除几乎都可以在几秒内完成。

  • 这意味着你可以轻松的做如下操作:

    • 无痛的上下文切换 创建分支试验一个想法,提交几次,切回你原来分支的状态,应用一个改动 patch,切回你原来正在试验的状态,将刚才应用的 patch 合并过来。
    • 基于角色的代码支线 你可能会有一个分支仅仅包含那些只存在于生产环境上的代码,另外有一个独立的分支用以合并测试环境代码,还有若干个更小一些的分支用于日常开发工作
    • 基于特性的工作流 为每一个新的特性创建新的分支,你可以方便平滑的在这些分支之间无缝切换,当这些特性的改动完成的时候,你可以将其合并入主分支,并把特性分支删掉。
    • 任意试验 创建一个分支专门用来试验,当觉得试验不理想的时候,直接删除掉即可,放弃掉之前的试验内容。这时候不会有任何其他人察觉到这个试验(甚至在这期间你还可以推送其他不相关的分支)

尤其是当你推送至远程仓库的时候,你不必推送所有分支,你可以选择只推送少数你愿意分享的分支,当然如果你愿意,也可以推送所有分支。这一点倾向于让开发者在试验很多新的想法的时候免除发布自己的未成熟的试验计划的顾虑。

当然,也有一些其他的系统可以部分实现上述的功能和优势,只是具体的执行会变的困难和容易出错。Git 让这些工作变得难以置信的简单,它在开发者学习其使用的同时就改变了开发者的工作模式。

5. 文件

  • 添加(git add)
git add # 在提交你修改的文件之前,你需要把它们添加到暂存区。如果该文件是新创建的,你可以执行将该文件添加到暂存区
git add . # Git会递归地将你执行命令时所在的目录中的所有文件添加上去,所以如果你将当前的工作目录作为参数,它就会追踪那儿的所有文件
git add -u # 使用-u参数调用了git add命令,会将本地有改动(包括删除和修改)的已经追踪的文件标记到暂存区中。
git add -A # 使用-A参数会将添加所有改动的已跟踪文件和未跟踪文件。
git add -i # 交互式的方式进行添加。
  • 删除(git rm)
rm命令删除的文件只是在本地进行了删除,尚未添加到暂存区,也就是说,直接在工作区删除,对暂存区和版本库没有任何影响。
git rm命令会将删除动作加入暂存区,这是执行提交动作,就从真正意义上执行了文件删除。
  • 移动或重命名(git mv)
git mv # 移动文件,git中以git rm和git add两条命令取而代之。
  • 清除(git clean)
    删除本地多余的目录和文件
git clean -nd # 显示要删除的内容,但是是预删除
git clean -fd # 强制删除多余的文件和目录
```shell
- 查看文件状态(git status)
```shell
git status # 查看你的代码在缓存与当前工作目录的状态
git status -s # 将结果以简短的形式输出
  • 查看本次修改内容(git diff)

git diff # 显示工作区和暂存区的差异
git diff FileName # 查看文件本次修改内容
git diff HEAD # 显示工作区和HEAD之间的差异
git diff --cached # 显示暂存区和HEAD之间的差异
git diff id1 id2 # 显示两次提交之间的差异
  • 提交(git commit)
git commit -m "文件版本内容" # 提交
git commit --amend # 修补式提交。
git commit --a # 对本地所有变更的文件执行提交操作,包括对本地修改的文件和删除的文件,但是不包括未被版本库跟踪的文件。但是这个命令最好不要使用,这样会丢掉Git暂存区带给用户的最大好处:对提交内容进行控制的能力
git commit --allow-empty # 允许执行空白提交
  • 查看修改履历(git log)
    git log 主要用来显示分支中提交更改的记录。当执行 git commit 以存储一个快照的时候,文件详单、提交消息和提交者的信息、此次提交所基于的快照都会被保存。
git log --pretty=oneline
git log --oneline # 可以显示更加短小的提交ID.
git log --graph # 显示何时出现了分支和合并等信息.
git log --pretty=raw # 显示提交对象的parent属性.
  • 回滚(git checkout)
git checkout branchname # 会改变HEAD头指针,主要用于切换分支
git checkout -b branchname # 用于创建一个新的分支,并且切换到创建的新的分支上
git checkout --filename # 用暂存区中的filename文件来覆盖工作区中的filename文件
git checkout  --filename # 用指定提交中的文件覆盖暂存区和工作区中对应的文件
git checkout -- .或者git checkout . # 用暂存区的所有文件直接覆盖本地文件,取消所有的本地的修改,是一条危险的操作

6. 版本控制

  • 版本(git rebase)

  • 版本(git reset)


把当前分支指向另一个位置,并且有选择的变动工作目录和索引

git reset --hard <commit> # 其中commit是可选项,可以使用引用或者提交ID,如果省略则相当于使用了HEAD的指向作为提交ID,完成的操作包括替换引用的指向,替换暂存区,替换工作区
git reset --soft <commit> # 其中commit是可选项,可以使用引用或者提交ID,如果省略则相当于使用了HEAD的指向作为提交ID。完成的操作主要是更改引用的指向,不改变暂存区和工作区
git reset # 等同于git reset HEAD,用HEAD指向的目录树重置暂存区
git reset -- filename # 将文件filename的改动撤出暂存区,暂存区其他文件不变
git reset HEAD --filename # 等同于git reset -- filename

提交 ID 可以是前一部分

  • 查看提交记录(git reflog)
git reflog
  • 查看 Git 对象(git cat-file)
git cat-file -t  # 查看Git对象的类型,主要的git对象包括tree,commit,parent,和blob等。
git cat-file -p  # 查看Git对象的内容
  • git grep
git grep # 可以用来搜索工作区中的文件内容
要查找git仓库里某个特定版本里的内容, 我们可以像下面一样在命令行末尾加上标签名(tag reference),git grep '文字内容' v1.0
  • 分支(git branch)
git branch # 显示当前所在的分支
git branch # 创建新的分支branchname
git branch # 基于提交创建新分支,新分支的分支名为
git branch -d # 删除名称为branchname的分支,删除时会检查所有的删除分支是否已经合并到其他分支,否则拒绝删除
git branch -D # 强制删除分支
git branch -m # 重命名分支
  • git archive
git archive # 对任意提交对应的目录树建立归档。
git archive -o latest.zip HEAD # 基于最新提交建立归档文件latest.zip
git archive -o partial.tar HEAD src doc # 只将目录src和doc建立到归档文件partial.tar中
git archive --format=tar --prefix=1.0/ v1.0 | gzip > foo-1.0.tar.gz # 基于里程碑v1.0建立归档,并且为归档中的文件添加目录前缀1.0

7. 原理

轻量和快速

Git 很快。Git 基本上所有的操作都在本地执行,这对于那些必须跟服务器通信的集中式系统是一个巨大的速度优势。
Git 一开始是为了管理 Linux Kernel 的源代码设计的,这意味着他从第一天诞生就拥有了处理大型仓库的高效优势。Git 使用 C 语言编写,减轻了使用更高级别编程语言的 Runtime 带来的性能损耗。Git 最开始的两个重要的设计目标就是性能和速度。

压力测试

让我们看一下与 SVN (一个通用的集中式存储版本控制系统,跟 CVS 和 Perforce 很像)相比下的常规操作的性能测试指标。这里指标是值越小,速度越快。
为了测试,我们在亚马逊的 AWS 的同样的可用区上新建了两个 Large 类型的计算服务器实例。每一个计算实例上都安装 Git 和 SVN。 我们把 Ruby 的源代码仓库拷贝到了 Git 和 SVN 的计算服务器示例上,两者都执行通用的操作。
在有些情况下,两者的命令和实际效果并不能完全对应起来。在这里,我们在常用的操作中选择相似效果的匹配情况。例如,对于 “提交” 的测试,在 Git 中我们也是计算 Push 的时间的。然而在大多数情况下,你可能实际上并不会在提交后马上就推送到服务器上,这在 SVN 上是不可分割的操作。

下面表格中所有的时间单位都是秒。

操作 描述 Git SVN 性能
倍数
提交文件
(A)
Add, commit and push 113 modified
files (2164+, 2259­)
0.64 2.60 4x
提交图片
(B)
Add, commit and push 1000 1k images 1.53 24.70 16x
对比当前
变动
Diff 187 changed files (1664+, 4859­)
against last commit
0.25 1.09 4x
对比最近
的变动
Diff against 4 commits back (269 changed/3609+,6898­) 0.25 3.99 16x
对比标签 Diff two tags against each other
(v1.9.1.0/v1.9.3.0)
1.17 83.57 71x
提交历史
(50)
Log of the last 50 commits (19k of output) 0.01 0.38 31x
提交历史
(全部)
Log of all commits (26,056 commits ­ 9.4M of output) 0.52 169.20 325x
提交历史
(文件)
Log of the history of a single file (array.c ­ 483 revs) 0.60 82.84 138x
更新 Pull of Commit A scenario (113 files changed, 2164+, 2259­) 0.90 2.82 3x
Blame Line annotation of a single file
(array.c)
1.91 3.04 1x

你需要注意的是,这已经是 SVN 最好的运行场景了 ­­ 一个没有任何负载的服务器,客户端和服务器之间的网络带宽达到 80MB/s。上文中的所有指标在受网络波动,或者在一个更差的网络环境下 SVN 的表现都更差,然而 Git 这边几乎所有的指标都不受影响。

很明显,在这些最常用的版本控制工具的操作中,甚至是在 SVN 的理想使用环境下,Git 在很多方面都大幅领先

一个 Git 比 SVN 慢的地方是初始化 clone 仓库。在这种情况下,Git 是在下载整个仓库历史而不是仅仅是最新版本的代码。上文中的表格所示,仅仅执行一次的操作影响并不是很大。

操作描述 Git(Shallow Clone)GitSVN Clone Git Clone 以及 shallow clone(浅 clone) vs SVN checkout 21.0 107.5 14.0 大小 (M)客户端在 clone/checkout 后的文件大小 (以 M 为单位)181.0132.0

另外一个有趣的点是,Git 和 SVN 在 Clone 或者 Checkout 到本地后的文件大小几乎差别不大,要知道对于 Git 来说,本地可是包含了整个项目历史。这也展示了 Git 在文件压缩和存储上的超高效率。

分布式

Git 最棒的特性之一就是分布式。这意味着,你要 clone 整个仓库而不是仅仅 checkout 分支的最新头部版本。

多个备份

在日常的使用场景中 Git 往往有多个备份。这意味着就算在使用一个中央存储式的工作流,每一个用户都在本地有一个服务器上的完整备份。这里的任意一个版本都可以在服务器端数据损坏或者丢失的时候推送回服务器以挽救损失。事实上,只要你的仓库不是只有一个 copy,Git 就不会存在单点问题。

任意工作流

因为 Git 拥有分布式特性和极好的分支系统,你可以在此基础上轻松实现大量的工作流模型。
集中式存储的工作流非常常见,特别是对于那些从传统的集中式代码版本管理系统转过来使用 Git 的人。Git 一样可以提供这种工作形式:每次 Push 必须要更新到远程仓库的最新版本。所以说大家还是像以前一样使用集中式存储的工作流往同一个服务器上 Push 代码依然没问题。

整合管理者工作流

另外一个常见的 Git 工作流是整合工作流。主要的仓库有一个单一的开发者维护(维护者)。其他若干开发者从这个仓库 clone,然后推送到他们自己的完全独立的仓库里面,最后请求维护者从主要仓库 Pull 那些他们在各自的仓库里面的改动。这种形式往往在 GitHub 上以开源的形式进行协作。

维护者和负责人工作流

对于一些更为复杂的项目来讲,像 Linux 内核这样的开发工作流也是很有效的。在这个模型中,负责人(lieutenants)负责整个项目的一些特定的子系统,他们合并所有跟那个子系统关联的变动。另外一个维护者(dictator,字面理解:独裁者)只能从他管辖的负责人这里获取变更,并将这些变更推送到主要仓库。然后所有人都从这个仓库获取更新。

数据校验

Git 的数据模型确保了项目内的每一个字节,每一个 bit 的一致性。提交的每一个文件都会使用校验和计算摘要,检出的时候也使用这个摘要值。没有任何可能会出现从仓库中获取的内容跟你存储的内容有任何差异。

在不改变 ID(校验和)的情况下也不可能出现改变任何文件,日期,提交说明或者任何其他在 Git 仓库中的数据。这就意味着,如果你有一个 commit ID,你不但可以确定这个版本的代码跟他提交的时候是一模一样的,而且这个版本之前的历史也没有发生任何改变。

大多数中央存储的版本控制系统默认不提供这样的校验整合。

暂存区域

不像其他系统, Git 有一个概念叫做 “暂存区域” 或者 “index”。这是一个在提交执行之前的临时的区域可以用来格式化和审阅改动内容的。

一个 Git 优于其他系统的功能是我们可以快速的暂存一些改动的文件,在工作目录中只提交部分改动的文件,或者文件改动的部分内容,以及在提交的时候在命令行里列出改动的文件列表。

暂存区域允许你仅仅暂存部分的文件改动,在你意识到你忘了提交其中一个文件之前,对文件进行两个逻辑上不相关的修改的日子已经一去不复返了。现在你可以仅仅暂存你当前提交需要改动的文件,其他的改动在下次提交再暂存。这个特性可以扩展到对文件进行的任何更改。

当然,Git 也允许你忽略掉暂存区域这个过程,你可以轻松的在 commit 命令后面添加 '­a' 选项来直接将所有改动提交。Git 会自动帮你先暂存到暂存区域,再执行提交。

存储密码

https 协议

如果使用的是 https 协议访问 git 仓库,与服务器端同步的时候每一次都会提示输入密码。解决这个问题的方式就是能让密码保存起来。

在 windows 下,我使用的是 git-credential-winstore。下载安装即可使用。

在 Mac 下,我使用的是 git-credential-osxkeychain。首先在终端中检测是否已经有 git-credential-osxkeychain,git credential-osxkeychain。提示 usage: git credential-osxkeychain <get|store|erase>, 代表有。

如果没有,下载这个工具,执行:

Move the file to the /usr/local/bin directory.
$ sudo mv git-credential-osxkeychain /usr/local/bin/

Make the file an executable:
$ chmod u+x /usr/local/bin/git-credential-osxkeychain
Configure git to use the helper.

$ git config --global credential.helper osxkeychain
# Set git to use the osxkeychain credential helper

如果存在的话,直接执行 git config --global credential.helper osxkeychain

在 Linux 下,执行 git config --global credential.helper store

操作完之后,检查下 .gitconfig 文件,看是否添加了 [credential] 字段。

如果需要取消设置,执行 git config --unset --global credential.helper

8. 常用工具

控制台

  • Windows
    • GitShell
    • Cmder
    • PowerShell

GUI

  • Windows
    • Git GUI
    • SourceTree

conventional-changelog

  • 追加
    conventional-changelog -p angular -i CHANGELOG.md -s
  • 全量生成
    conventional-changelog -p angular -i CHANGELOG.md -s -r 0

9. git 基本命令集合


命令 注释
git init # 初始化本地 git 仓库(创建新仓库)
git config --global user.name "xxx" # 配置用户名
git config --global user.email "xxx@xxx.com" # 配置邮件
git config --global color.ui true # git status 等命令自动着色
git config --global color.status auto
git config --global color.diff auto
git config --global color.branch auto
git config --global color.interactive auto
git clone git+ # clone 远程仓库
git status # 查看当前版本状态(是否修改)
git add xyz # 添加 xyz 文件至 index
git add . # 增加当前子目录下所有更改过的文件至 index
git commit -m 'xxx' # 提交
git commit --amend -m 'xxx' # 合并上一次提交(用于反复修改)
git commit -am 'xxx' # 将 add 和 commit 合为一步
git rm xxx # 删除 index 中的文件
git rm -r * # 递归删除
git log # 显示提交日志
git log -1 # 显示 1 行日志 -n 为 n 行
git log -5
git log --stat # 显示提交日志及相关变动文件
git log -p -m
git show dfb02e6e4f2f7b573337763e5c0013802e392818 # 显示某个提交的详细内容
git show dfb02 # 可只用 commitid 的前几位
git show HEAD # 显示 HEAD 提交日志
git show HEAD^ # 显示 HEAD 的父(上一个版本)的提交日志 ^^ 为上两个版本 ^5 为上 5 个版本
git tag # 显示已存在的 tag
git tag -a v2.0 -m 'xxx' # 增加 v2.0 的 tag
git show v2.0 # 显示 v2.0 的日志及详细内容
git log v2.0 # 显示 v2.0 的日志
git diff # 显示所有未添加至 index 的变更
git diff --cached # 显示所有已添加 index 但还未 commit 的变更
git diff HEAD^ # 比较与上一个版本的差异
git diff HEAD -- ./lib # 比较与 HEAD 版本 lib 目录的差异
git diff origin/master..master # 比较远程分支 master 上有本地分支 master 上没有的
git diff origin/master..master --stat # 只显示差异的文件,不显示具体内容
git remote add origin git+ # 增加远程定义(用于 push/pull/fetch)
git branch # 显示本地分支
git branch --contains 50089 # 显示包含提交 50089 的分支
git branch -a # 显示所有分支
git branch -r # 显示所有原创分支
git branch --merged # 显示所有已合并到当前分支的分支
git branch --no-merged # 显示所有未合并到当前分支的分支
git branch -m master master_copy # 本地分支改名
git checkout -b master_copy # 从当前分支创建新分支 master_copy 并检出
git checkout -b master master_copy # 上面的完整版
git checkout features/performance # 检出已存在的 features/performance 分支
git checkout --track hotfixes/BJVEP933 # 检出远程分支 hotfixes/BJVEP933 并创建本地跟踪分支
git checkout v2.0 # 检出版本 v2.0
git checkout -b devel origin/develop # 从远程分支 develop 创建新本地分支 devel 并检出
git checkout -- README # 检出 head 版本的 README 文件(可用于修改错误回退)
git merge origin/master # 合并远程 master 分支至当前分支
git cherry-pick ff44785404a8e # 合并提交 ff44785404a8e 的修改
git push origin master # 将当前分支 push 到远程 master 分支
git push origin :hotfixes/BJVEP933 # 删除远程仓库的 hotfixes/BJVEP933 分支
git push --tags # 把所有 tag 推送到远程仓库
git fetch # 获取所有远程分支(不更新本地分支,另需 merge)
git fetch --prune # 获取所有原创分支并清除服务器上已删掉的分支
git pull origin master # 获取远程分支 master 并 merge 到当前分支
git mv README README2 # 重命名文件 README 为 README2
git reset --hard HEAD # 将当前版本重置为 HEAD(通常用于 merge 失败回退)
git rebase
git branch -d hotfixes/BJVEP933 # 删除分支 hotfixes/BJVEP933(本分支修改已合并到其他分支)
git branch -D hotfixes/BJVEP933 # 强制删除分支 hotfixes/BJVEP933
git ls-files # 列出 git index 包含的文件
git show-branch # 图示当前分支历史
git show-branch --all # 图示所有分支历史
git whatchanged # 显示提交历史对应的文件修改
git revert dfb02e6e4f2f7b573337763e5c0013802e392818 # 撤销提交 dfb02e6e4f2f7b573337763e5c0013802e392818
git ls-tree HEAD # 内部命令:显示某个 git 对象
git rev-parse v2.0 # 内部命令:显示某个 ref 对于的 SHA1 HASH
git reflog # 显示所有提交,包括孤立节点
git show HEAD@{5}
git show master@{yesterday} # 显示 master 分支昨天的状态
git log --pretty=format:'%h %s' --graph # 图示提交日志
git show HEAD~3
git show -s --pretty=raw 2be7fcb476
git stash # 暂存当前修改,将所有至为 HEAD 状态
git stash list # 查看所有暂存
git stash show -p stash@{0} # 参考第一次暂存
git stash apply stash@{0} # 应用第一次暂存
git grep "delete from" # 文件中搜索文本“delete from”
git grep -e '#define' --and -e SORT_DIRENT
git gc
git fsck

10. git 资料

11. 常见 err

fatal: refusing to merge unrelated histories

添加可选项 --allow-unrelated-histories

git pull origin master --allow-unrelated-histories

error:src refspec master does not match any

主要是没有要同步的文件

  • 第一次 git 操作的时候,git 会给我如下的提示:
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

When push.default is set to 'matching', git will push local branches
to the remote branches that already exist with the same name.

Since Git 2.0, Git defaults to the more conservative 'simple'
behavior, which only pushes the current branch to the corresponding
remote branch that 'git pull' uses to update the current branch.

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

其实就是告诉我要设置下 push.default,执行 git config --global push.default simple 即可。

Git 忽略规则和.gitignore 规则不生效的解决办法

Git 忽略规则:

在 git 中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如果没有这个文件,则需自己手工建立此文件)。这个文件每一行保存了一个匹配的规则例如:

  • 此为注释 – 将被 Git 忽略

  • *.sample    # 忽略所有 .sample 结尾的文件
  • !lib.sample    # 但 lib.sample 除外
  • /TODO    # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
  • build/    # 忽略 build/ 目录下的所有文件
  • doc/*.txt   # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

.gitignore 规则不生效的解决办法

把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore 只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore 是无效的。那么解决方法就是先把本地缓存删除(改变成未被追踪状态),然后再提交:

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

CHANGELOG

追加

conventional-changelog -p angular -i CHANGELOG.md -s

全量生成

conventional-changelog -p angular -i CHANGELOG.md -s -r 0

git hook 实现代码自动更新

Git 可以定制一些钩子,这些钩子可以在特定的情况下被执行,分为 Client 端的钩子和 Server 端的钩子。Client 端钩子被 operation 触发,比如 commit,merge 等,Server 端钩子被网络动作触发,比如 pushed commits。

那么钩子是放在哪的呢?
在.git/hooks/文件夹下。当你 init 一个仓库的时候,下边会有一些钩子的例子,以.sample 结尾。

那么钩子什么时候被执行,Git 预定义了触发时机:

  • ClientSide hooks:
    1. pre-commit,当执行 commit 动作时先执行此 hook,可以用此 hook 做一些检查,比如代码风格检查,或者先跑测试。
    2. prepare-commit-msg, 当 commit 时需要输入 message 前会触发此 hook,可以用此 hook 来定制自己的 default message 信息。
    3. commit-msg,当用户输入 commit 的 message 后被触发,可以用此 hook 校验 message 的信息,比如是否符合规定,有没有 cr 等。
    4. post-commit, 当 commit 完成后被触发,可以用此 hook 发送 notification 等。
    5. pre-rebase, rebase 之前会被触发,可以用此 hook 来拒绝所有的已经 push 的 commits 进行 rebase 操作。
    6. post-merge, 当 merge 成功后,会触发此 hook。
    7. pre-push, 当 push 时,remote refs 被更新,但是在所有的 objects 传输前被触发。
    8. pre-auto-gc, 当 git gc --auto 执行前被触发。在垃圾回收之前做一些验证或备份是挺不错的。
  • ServerSide hooks:
    1. pre-receive, 当收到 push 动作之前会被执行。
    2. update, 也是收到 push 动作之前被执行,但是有可能被执行多次,每个 branch 一次。
    3. post-receive, 当 push 动作已经完成的时候会被触发,可以用此 hook 来 push notification 等,比如发邮件,通知持续构建服务器等。
#!/bin/sh
# 修改git项目server端目录下 .git/hooks/post-receive.sample文件,该挂钩在push完结以后运行,取掉.sample启用它,内加入执行脚本,其中变量需修改成两个项目在本机的路径,以我在服务器上的测试脚本为例:

#zh-jssdk 项目存放路径,需修改
zh_jssdk_pro_path="/home/zhaojianping/weizhan/zh-jssdk/"
#文件夹相对路径,一般不需要修改
zh_jssdk_dir_path="dist/"
#wmp 项目存放路径,需修改
weizhan_wmp_pro_path="/home/zhaojianping/weizhan/wmp/"
#文件夹相对路径,一般不需要修改
weizhan_wmp_dir_path="wmp-webapp/src/main/resources/static/wmp/common/zh-sdk"

cd ${zh_jssdk_pro_path}
unset GIT_DIR
git pull
cd ${weizhan_wmp_pro_path}
unset GIT_DIR
git checkout master
for i in $(git branch -a)
do
notMaster=$(echo $i | grep "master")
remoteBranch=$(echo $i | grep "remotes/origin/")
if [[ "$notMaster"x == ""x ]]
then
        if [[ "$remoteBranch" != "" ]]
        then
        branchName=${i##*/}
        git branch -D ${branchName}
        git checkout "$i" -b ${branchName}
        git pull
        git rm -rf ${weizhan_wmp_dir_path}
        mkdir "$weizhan_wmp_dir_path"
        git commit -m 'Delete old files commit!!--by shell [zh-jssdk push!]'
        cp -rf ${zh_jssdk_pro_path}${zh_jssdk_dir_path}* ${weizhan_wmp_pro_path}${weizhan_wmp_dir_path}
        git add .
        git commit -m 'Update new files commit!!--by shell [zh-jssdk push!]'
        git push
        git checkout master
        git branch -D ${branchName}
        fi
fi
done

记住所有的 hook 都应该是可被执行的。chmod u+x your_hook

  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...