Earth Guardian

You are not LATE!You are not EARLY!

0%

Git 相关操作

设置

全局设置

全局设置使用 gig config --global 参数,全局配置文件路径 ~/.gitconfig ,即家目录下。

  • 中文文件名或路径被转义
    在使用git的时候,经常会碰到有一些中文文件名或者路径被转义成 \xx\xx\xx 之类的
    示例:fang/\344\272\244\346\230\223\346\265\201\347\250\213/
    解决方案: xmt@server005:~$ git config --global core.quotepath false
  • GUI 中代码包含中文时,显示乱码
    解决方案: git config --global gui.encoding utf-8

  • Windows 中回车换行符的处理
    github处理回车换行
    git config --global core.autocrlf true

  • 别名或者短命令 alias
    对于比较长的命令可以使用 tab 键补全,也可以通过 alias 定制命令的别名来缩短:
    格式:git config --global alias.新名称 '完整命令'
    示例:git config --global alias.l 'log -1' ,即 git log -1 查看最近一条提交记录,可以使用短命令 git l 来实现。

也可以直接打开 ~/.gitconfig 文件,批量修改:

1
2
3
4
5
6
[core]
quotepath = false
autocrlf = true
[alias]
l = log -1
co = checkout

当前仓库设置

使用 git config 时不带 --global 参数,可以针对每个仓库做定制化。
配置文件在每个仓库下面:.git/config

  • 用户名和邮箱
1
2
xmt@server005:~$ git config user.name xmt
xmt@server005:~$ git config user.email xmt@company.com

分支

查看所有分支(本地和远程)

git branch -a 或者 git branch -av

新建分支

  • git branch test_branch
  • git checkout –b test_branch

新建空分支

git checkout --orphan empty_branch
空分支不会有任何提交历史,通常可以用来新建 todo 或者 docs 分支。
git rm -rf . ;git commit -m 'new empty branch,在提交修改后(也就是生成一次提交记录),分支才能通过 git branch -a 查看到。

删除分支

git branch -d test_branch 或者 git branch -D test_branch

新建远程分支

git push origin <branchName>:<branchName>
注释:origin 是默认的远程版本库名称,事实上 git push origin master 的意思是 git push origin master:master 。将本地的 master 分支推送至远端的 master 分支,如果没有就新建一个

删除远程分支

1
2
git push origin --delete <branchName>   // 使用 --delete
git push origin :<branchName> // 使用空名称

修改分支名称

修改本地分支名称:

1
git branch -m oldName newName

修改远程分支名称,可以先将远程分支删除,然后再推动本地新的分支名。

标签

查看所有标签

git tag 查看仓库的所有标签。

新建标签

1
2
3
$ git tag v1.0                            // 当前提交上打标签
$ git tag v1.0 f52c633 // 指定提交上打标签
$ git tag -a v1.0 -m 'comments.' f52c633 // 指定提交上,指定标签名,并添加注释

新建远程标签

将本地 v1.0 推送到远程仓库:

1
git push origin v1.0

删除标签

1
2
git tag -d <tagname>                    // 删除本地标签
git push origin :refs/tags/<tagname> // 删除远程仓库标签

提交

重命名目录

1
2
git mv ipc 005_ipc
renamed: docs/ipc/Serializable_Parcelable.md -> docs/005_ipc/Serializable_Parcelable.md

提交到 stack

回退与恢复

本地修改回退

git reset --hard ab2b3747704c204bd5a810d5c445d4394647cbfb
--hard 表示将本地所有修改回退到这个 commit

回退 unstage

1
2
3
4
5
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: .gitignore
new file: data/jobs.txt

比如上面的 .gitignore, data/jobs.txt 两个文件已经通过 git add 添加,但是还没有提交 commit;可以通过 git reset HEAD 回退到 unstage 状态。

修复已提交的错误

已提交是指 commit 后但是没有 push 到远程仓库。如果已经 push 到远程仓库,无法修改。

  • 修复后新建一个 commit 提交
    这种方法是最简单的,但是会形成多余的 commit
  • 共用上次错误提交的 commit
    不管是想修改文件还是提交记录,都可以使用 git commit --amend 来修复上次错误提交。如果仅仅是修改提交记录,直接执行重新编辑提交记录即可。如果是修改代码,需要先 add 再执行:
    1
    2
    3
    ubuntu$ vim a.txt           // 修改代码
    ubuntu$ git add a.txt // 添加到 stage
    ubuntu$ git commit --amend // 使用上次的 commit 重新提交这次修改

恢复误操作 reflog

  • 先查看所有的修改记录 git reflog
1
2
3
$ git reflog
570b79a HEAD@{0}: reset: moving to 70b79a71fdf388eaa0cf4bc57849cf5aae6212d
0dab5ea HEAD@{1}: commit: add use case framework.
  • 其中 570b79a 为误操作
  • 回退这个误操作
    git reset --hard 0dab5ea

合并 merge

cherry-pick 将分支 A 的提交合入到分支 B

  • 查看分支 A 上的 commitid,如:7eef2cda41edc07c8ee2c5ba5dbc9f1602144c88
  • 切换到分支 B ,合入这个 commitid的修改
  • git cherry-pick 7eef2cda41edc07c8ee2c5ba5dbc9f1602144c88 ,合入后会重新生成 id

查看提交

查看 log

  • 基本命令 git log
  • 按照指定格式显示

示例:git log --pretty=format:"%an %ae %ad %cn %ce %cd %cr %s"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
选项     说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明

示例:按照 commit,作者,提交说明这三项查看 log,并通过 | 分隔,方便分析
git log --pretty=format:"%H | %an | %s" > log

查看某次提交

  • 基本命令:git show commit_id
1
2
3
4
5
6
7
8
9
10
xmt@server005:~$ git show 8593d90fd5c35ef6a9d88910651e528116914dd0
commit 8593d90fd5c35ef6a9d88910651e528116914dd0
Author: xmt <xmt@30d99328-7319-4b8f-a506-b34d821aa509>
Date: Fri Dec 5 08:52:39 2014 +0000

解决耳机识别问题

git-svn-id: http://10.1.1.253/android/Marvell/pxa1908/branches/PO9041/trunk/po9041_trunk@83 30d99328-7319-4b8f-

a506-b34d821aa509

如果不带 commit_id ,默认为查看最近一次

  • 查看某次提交修改了哪些文件,参数 -numstat
    git show –numstat 8593d90fd5c35ef6a9d88910651e528116914dd0

查看修改状态

基本命令:git whatchanged 。示例:查看该次提交文件修改状态,如增加,修改,删除等
git whatchanged -1 8593d90fd5c35ef6a9d88910651e528116914dd0

修改提交后的作者信息

使用了错误的账号提交 commit 后,需要修改作者信息,参考步骤如下。

修改上次提交的作者信息

  • 当前 git 仓库设置正确的作者信息
    git config user.name/email *** ,设置正确的作者信息。
  • 修改上次提交的作者信息
    git commit --amend --reset-author ,使用当前作者信息,重新修改上次提交。

修改某次提交的作者信息

  • 找到需要修改的提交 id
    git log 查看并找到需要修改的提交 id ,比如如下记录中,需要修改第二条提交记录 b9b1f623bab552c47e4f0e78d159fa282bd95632
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    commit ac5da90b4095d391701a74ab77eada36c35dc015
    Author: red <red@mail.com>
    Date: Mon Feb 18 14:23:46 2019 +0800

    update b to c

    commit b9b1f623bab552c47e4f0e78d159fa282bd95632
    Author: red <red@mail.com>
    Date: Mon Feb 18 14:23:21 2019 +0800

    update a to b

    commit da8a5a3c1039c77146eb9181bbe1778bcebcd797
    Author: red <red@mail.com>
    Date: Mon Feb 18 14:20:34 2019 +0800

    add a.txt
  • 使用 git rebase -i 命令
    rebase -i 指定到被修改 id 的前一个 id: (或者使用 git rebase -i HEAD~n ,其中 n 为倒数第几个提交记录):
    1
    2
    3
    4
    5
    6
    git rebase -i da8a5a3c1039c77146eb9181bbe1778bcebcd797
    // 在弹出的编辑框中,将第二条记录前的 pick 修改为 edit,保存退出
    edit b9b1f62 update a to b // 目标 id,重置这条记录的作者信息
    pick ac5da90 update b to c

    # Rebase da8a5a3..ac5da90 onto da8a5a3
    修改完毕后,目标 id 提交记录在当前仓库中,成为最后一条提交记录。(那原本的最后一条提交记录呢??向后看)
  • 修改上次提交的作者信息
    使用 git commit --amend --reset-author 命令,重置上次提交记录(也就是当前目标 id )的作者信息。
  • 使用 git rebase --continue 命令
    使用 rebase --continue 命令,将分支恢复(即将最后一条提交记录复原)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ git rebase --continue
    Successfully rebased and updated refs/heads/master.
    $ git log
    commit 63df1273b7cc28905e73af4579346fc0d4f3e950
    Author: red <red@mail.com>
    Date: Mon Feb 18 14:23:46 2019 +0800

    update b to c

    // 目标 id 的作者信息已经被修改
    commit a3c971465967df8332acb8ec5d5117541a892085
    Author: modify <modify@mail.com>
    Date: Mon Feb 18 14:39:33 2019 +0800

    update a to b

    commit da8a5a3c1039c77146eb9181bbe1778bcebcd797
    Author: red <red@mail.com>
    Date: Mon Feb 18 14:20:34 2019 +0800

Patch 相关操作

制作 patch

  • 制作单次提交的 patch
    git format-patch -1 ab2b3747704c204bd5a810d5c445d4394647cbfb
    其中:-1 表示单次提交
  • 某次提交后的所有修改,每次提交都生成一个 patch
    git format-patch -s ab2b3747704c204bd5a810d5c445d4394647cbfb
    其中:-s 表示某次提交后的所有修改。但不包含当前 commit 的这次修改

合入 patch

git am patchname.patch

将多个 commit 合并为一个 patch

  • 分别将这几个 commit 生成对应的 patch
  • 新建两个分支 patches_branchmerge_branch
    patches_branch:用于提交多个分散的patch
    merge_branch:用于将 patches_branche 上的修改 merge 过来,生成单独 patch
  • 两个分支都回退到第一个 commit 之前
    git reset --hard ab2b3747704c204bd5a810d5c445d4394647cbfb
    --hard 表示将本地所有修改回退到这个 commit
  • patches_branch 分支上,通过 git am 合入第一步生成的所有 patch 文件
  • merge_branch 分支上,将所有修改 merge 过来,提交并生成一个新的 commit
    git merge patches_branch –squash
    其中:参数 –squash 表示放弃修改的历史信息
  • 将这个 commit 制作成新的 patch 。至此,所有修改生成单个 patch 文件完成

制作两个分支之间差异 patch

master 新建 dev 分支,并在 dev 分支上做多次修改提交后,比较 devmaster 两个分支间的差异,并生成 patch 文件。

  • 比较两个分支间的差异
    git log master..dev ,查看有多少次修改记录。
  • 将两个分支间的差异生成多个 patch 文件
    git format-patch master..dev ,每次修改提交都生成一个 patch 文件。
  • 将两个分支间的差异生成一个总的 patch 文件
    git diff master..dev > new.patch ,生成单独文件。

注意: masterdev 的顺序不能反,否则不会有任何文件生成。

仓库相关

提交到远程仓库 push

  • 默认提交
    git push 默认提交到远程仓库 originmaster 分支,默认提交实际对应的命令为 git push origin master:master
  • 提交单独分支
    git push origin dev:dev ,提交 dev 分支到远程仓库。注意这条命令如果冒号 : 前面为空,表示删除远程仓库的 dev 分支。
  • 提交所有分支 --all
    git push --all origin ,将本地所有分支都提交到远程仓库。

远程仓库地址切换

如原始地址为:https://username@163.com@github.com
切换到:git@github.com:username/SoundRecorder.git

  • 查看地址
1
2
3
git remote -v
origin https://github.com/username/SoundRecorder (fetch)
origin https://github.com/username/SoundRecorder (push)
  • 切换地址
    git remote set-url origin git@github.com:username/SoundRecorder.git

  • 再次查看确认

1
2
3
git remote -v
origin git@github.com:username/SoundRecorder.git (fetch)
origin git@github.com:username/SoundRecorder.git (push)

使用两个远程仓库地址同时备份

示例:同时在 github,gitlab 上新建两个 git 仓库

  • github 下载仓库
    git clone git@github.com:username/SoundRecorder.git

  • 在当前 git 目录下,远程添加新仓库分支
    git remote set-url --add origin git@gitlab.com:username/SoundRecorder.git
    .git/config 文件中查看:

    1
    2
    3
    4
    [remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@github.com:username/SoundRecorder.git
    url = git@gitlab.com:username/SoundRecorder.git
  • 获取新仓库分支信息
    git fetch git@gitlab.com:username/SoundRecorder.git

  • 同步新仓库最新文件
    git pull git@gitlab.com:username/SoundRecorder.git

  • 同步两个仓库,并提交到服务器上
    git push origin master

  • 后续每次更新后,push 到服务器上时,会同时备份到两个远程仓库
    git push

使用两个远程仓库地址分别备份

依然使用上面的例子,但是在添加第二个仓库地址时使用 git remote add :

  • github 下载仓库
    git clone git@github.com:username/SoundRecorder.git

  • 在当前 git 目录下,远程添加新仓库分支
    git remote add gitlab git@gitlab.com:username/SoundRecorder.git
    .git/config 文件中查看,除了默认的远程版本仓库 origin 外,还多了一个新加的 gitlab 远程仓库名:

    1
    2
    3
    4
    5
    6
    [remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@github.com:username/SoundRecorder.git
    [remote "gitlab"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@gitlab.com:username/SoundRecorder.git
  • 后续每次更新后,需要 push 2 次,每次备份一个远程仓库
    github 仓库备份:git push origin
    gitlab 仓库备份:git push gitlab
    上面两条命令仅仅是提交 master 分支。如果 github 上需要提交的正式修改,而 gitlab 上希望备份本地所有分支及其临时修改。可以使用 --all 强制提交所有分支,或者使用 --mirror 直接备份所有修改:git push --all gitlab 或者 git push --mirror git@gitlab.com:username/SoundRecorder.git 。并且 --mirror 备份的方式并不需要新建远程仓库,使用假名在当前本地仓库上(不要设置全局参数)新建一个短命令非常高效,推荐使用 --mirror 的方式。

  • 远程默认仓库 origin
    缺省情况下,不需要修改,默认就是 origin 。如果出现了以外,可以通过命令参数 -u 改回来:git push -u origin master 提交。对应的配置文件为 branch.master.remote=origin

仓库迁移

  • clone 裸仓库
    git clone --bare https://github.com/exampleuser/old-repository.git

  • push mirror

1
2
cd old-repository.git
git push --mirror https://github.com/exampleuser/new-repository.git

仓库镜像并更新

  • 镜像仓库
    git clone --mirror https://github.com/exampleuser/old-repository.git

  • 镜像同步更新

1
2
cd old-repository.git
git remote update // 同步更新镜像仓库的命令