Git
Posted petewell
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Git相关的知识,希望对你有一定的参考价值。
- 常用命令
- 一、新建代码库
- 二、配置
- 三、增加/删除文件
- 四、代码提交
- 五、分支
- 六、标签
- 七、查看信息
- 八、远程同步
- 九、撤销
- 十、其他
- Q&A
- 使用git rebase合并多次commit
- 如何解决gitk中文乱码,git ls-files 中文文件名乱码问题?
- 如何处理本地有更改需要从服务器合入新代码的情况?
- stash
- 如何合并 fork 的仓库的上游更新?
- 如何通过 TortoiseSVN 带的 TortoiseMerge.exe 处理 git 产生的 conflict?
- 不想跟踪的文件已经被提交了,如何不再跟踪而保留本地文件?
- 如何不建立一个没有 parent 的 branch?
- submodule 的常用命令
- 删除远程 tag
- 清除未跟踪文件
- 忽略文件属性更改
- patch
- 只下载最新代码
- 基于某次 commit 创建分支
- 恢复单个文件到指定版本
- 设置全局 hooks
- 查看某次 commit 的修改内容
- 查看某个文件的修改历史
- 查看最近两次的修改内容
- 应用已存在的某次更改
- 命令行自动补全
- 文件每一行变更明细
- 找回曾经的历史
常用命令
日常使用只要记住下图6个命令,就可以了。但是熟练使用,恐怕要记住60~100个命令。
下面是我整理的常用 Git 命令清单。几个专用名词的译名如下。
- Workspace:工作区
- Index / Stage:暂存区
- Repository:仓库区(或本地仓库)
- Remote:远程仓库
一、新建代码库
# 在当前目录新建一个Git代码库
$ git init
# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]
# 下载一个项目和它的整个代码历史
$ git clone [url]
二、配置
Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。
# 显示当前的Git配置
$ git config --list
# 编辑Git配置文件
$ git config -e [--global]
# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
三、增加/删除文件
# 添加指定文件到暂存区
$ git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
$ git add [dir]
# 添加当前目录的所有文件到暂存区
$ git add .
# 添加每个变化前,都会要求确认
# 对于同一个文件的多处变化,可以实现分次提交
$ git add -p
# 删除工作区文件,并且将这次删除放入暂存区
$ git rm [file1] [file2] ...
# 停止追踪指定文件,但该文件会保留在工作区
$ git rm --cached [file]
# 改名文件,并且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]
四、代码提交
# 提交暂存区到仓库区
$ git commit -m [message]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
五、分支
# 列出所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支,并切换到该分支
$ git checkout -b [branch]
# 新建一个分支,指向指定commit
$ git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
六、标签
# 列出所有tag
$ git tag
# 新建一个tag在当前commit
$ git tag [tag]
# 新建一个tag在指定commit
$ git tag [tag] [commit]
# 删除本地tag
$ git tag -d [tag]
# 删除远程tag
$ git push origin :refs/tags/[tagName]
# 查看tag信息
$ git show [tag]
# 提交指定tag
$ git push [remote] [tag]
# 提交所有tag
$ git push [remote] --tags
# 新建一个分支,指向某个tag
$ git checkout -b [branch] [tag]
七、查看信息
# 显示有变更的文件
$ git status
# 显示当前分支的版本历史
$ git log
# 显示commit历史,以及每次commit发生变更的文件
$ git log --stat
# 搜索提交历史,根据关键词
$ git log -S [keyword]
# 显示某个commit之后的所有变动,每个commit占据一行
$ git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
$ git log [tag] HEAD --grep feature
# 显示某个文件的版本历史,包括文件改名
$ git log --follow [file]
$ git whatchanged [file]
# 显示指定文件相关的每一次diff
$ git log -p [file]
# 显示过去5次提交
$ git log -5 --pretty --oneline
# 显示所有提交过的用户,按提交次数排序
$ git shortlog -sn
# 显示指定文件是什么人在什么时间修改过
$ git blame [file]
# 显示暂存区和工作区的差异
$ git diff
# 显示暂存区和上一个commit的差异
$ git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"
# 显示某次提交的元数据和内容变化
$ git show [commit]
# 显示某次提交发生变化的文件
$ git show --name-only [commit]
# 显示某次提交时,某个文件的内容
$ git show [commit]:[filename]
# 显示当前分支的最近几次提交
$ git reflog
八、远程同步
# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]
# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]
# 上传本地指定分支到远程仓库
$ git push [remote] [branch]
# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force
# 推送所有分支到远程仓库
$ git push [remote] --all
九、撤销
# 恢复暂存区的指定文件到工作区
$ git checkout [file]
# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
$ git checkout .
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]
# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert [commit]
# 暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop
十、其他
# 生成一个可供发布的压缩包
$ git archive
Q&A
使用git rebase合并多次commit
将多次commit合并,只保留一次提交历史。
- 首先使用git log查看一下提交历史
commit 50b340566f43f5ba02ce06c071228fb475f137a8 (HEAD -> master)
Author: likonion <likonion@outlook.com>
Date: Sat Jul 7 11:07:03 2018 +0800
test9
commit 7d3c9b5cf55a2eea0a1456548b88bd4a0fc4c7c2
Author: likonion <likonion@outlook.com>
Date: Sat Jul 7 11:06:55 2018 +0800
test8
commit 778b26afdd4a26f6c2d3d3425dfa015db620964f
Author: likonion <likonion@outlook.com>
Date: Sat Jul 7 11:06:45 2018 +0800
test7
commit c7cf4bb88b647dd6e2d16362ff78ee6edf768082 (origin/master, origin/HEAD)
Author: likonion <likonion@outlook.com>
Date: Sat Jul 7 09:55:00 2018 +0800
test5
test6
commit 3a9e31affd1b2e477ff02b5f5fb36ee105f90d60
Author: likonion <likonion@outlook.com>
Date: Sat Jul 7 09:54:36 2018 +0800
git rebase -i c7cf4bb88(我们要合并的commit的前一个)
pick 778b26a test7
pick 7d3c9b5 test8
pick 50b3405 test9
# Rebase c7cf4bb..50b3405 onto c7cf4bb (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
~
~
~
~
~
~
~
"~/Documents/git-spaces/git-test/.git/rebase-merge/git-rebase-todo" 22L, 696C
pick 778b26a test7
squash 7d3c9b5 test8
squash 50b3405 test9
将后面两个改成squash,就是合并到第一个上去
如果没有冲突就可以看到这个界面
# This is a combination of 3 commits.
# This is the 1st commit message:
test7
# This is the commit message #2:
test8
# This is the commit message #3:
test9
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sat Jul 7 11:06:45 2018 +0800
#
# interactive rebase in progress; onto c7cf4bb
# Last commands done (3 commands done):
# squash 7d3c9b5 test8
# squash 50b3405 test9
# No commands remaining.
# You are currently rebasing branch 'master' on 'c7cf4bb'.
#
# Changes to be committed:
# modified: 1.html
#
~
"~/Documents/git-spaces/git-test/.git/COMMIT_EDITMSG" 28L, 619C
保存退出
$ git rebase -i c7cf4bb88
[detached HEAD 089d8b7] test7
Date: Sat Jul 7 11:06:45 2018 +0800
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/master.
最后git push -f
$ git push -f
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 331 bytes | 331.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:likonion/git-test.git
c7cf4bb..089d8b7 master -> master
如何解决gitk中文乱码,git ls-files 中文文件名乱码问题?
在~/.gitconfig中添加如下内容
[core]
quotepath = false
[gui]
encoding = utf-8
[i18n]
commitencoding = utf-8
[svn]
pathnameencoding = utf-8
参考 http://zengrong.net/post/1249.htm
如何处理本地有更改需要从服务器合入新代码的情况?
git stash
git pull
git stash pop
stash
查看 stash 列表:
git stash list
查看某一次 stash 的改动文件列表(不传最后一个参数默认显示最近一次):
git stash show stash@{0}
以 patch 方式显示改动内容
git stash show -p stash@{0}
如何合并 fork 的仓库的上游更新?
git remote add upstream https://upstream-repo-url
git fetch upstream
git merge upstream/master
如何通过 TortoiseSVN 带的 TortoiseMerge.exe 处理 git 产生的 conflict?
- 将 TortoiseMerge.exe 所在路径添加到
path
环境变量。 - 运行命令
git config --global merge.tool tortoisemerge
将 TortoiseMerge.exe 设置为默认的 merge tool。 -
在产生 conflict 的目录运行
git mergetool
,TortoiseMerge.exe 会跳出来供你 resolve conflict。也可以运行
git mergetool -t vimdiff
使用-t
参数临时指定一个想要使用的 merge tool。
不想跟踪的文件已经被提交了,如何不再跟踪而保留本地文件?
git rm --cached /path/to/file
,然后正常 add 和 commit 即可。
如何不建立一个没有 parent 的 branch?
git checkout --orphan newbranch
此时 git branch
是不会显示该 branch 的,直到你做完更改首次 commit。比如你可能会想建立一个空的 gh-pages branch,那么:
git checkout --orphan gh-pages
git rm -rf .
// add your gh-pages branch files
git add .
git commit -m "init commit"
submodule 的常用命令
添加 submodule
git submodule add git@github.com:philsquared/Catch.git Catch
这会在仓库根目录下生成如下 .gitmodules 文件并 clone 该 submodule 到本地。
[submodule "Catch"]
path = Catch
url = git@github.com:philsquared/Catch.git
更新 submodule
git submodule update
当 submodule 的 remote 有更新的时候,需要
git submodule update --remote
删除 submodule
在 .gitmodules 中删除对应 submodule 的信息,然后使用如下命令删除子模块所有文件:
git rm --cached Catch
clone 仓库时拉取 submodule
git submodule update --init --recursive
删除远程 tag
git tag -d v0.0.9
git push origin :refs/tags/v0.0.9
或
git push origin --delete tag [tagname]
清除未跟踪文件
git clean
可选项:
选项 | 含义 |
---|---|
-q, –quiet | 不显示删除文件名称 |
-n, –dry-run | 试运行 |
-f, –force | 强制删除 |
-i, –interactive | 交互式删除 |
-d | 删除文件夹 |
-e, –exclude |
忽略符合 |
-x | 清除包括 .gitignore 里忽略的文件 |
-X | 只清除 .gitignore 里忽略的文件 |
忽略文件属性更改
因为临时需求对某个文件 chmod 了一下,结果这个就被记为了更改,有时候这是想要的,有时候这会造成困扰。
git config --global core.filemode false
参考:How do I make Git ignore file mode (chmod) changes?
patch
将未添加到暂存区的更改生成 patch 文件:
git diff > demo.patch
将已添加到暂存区的更改生成 patch 文件:
git diff --cached > demo.patch
合并上面两条命令生成的 patch 文件包含的更改:
git apply demo.patch
将从 HEAD 之前的 3 次 commit 生成 3 个 patch 文件:
(HEAD 可以换成 sha1 码)
git format-patch -3 HEAD
生成 af8e2 与 eaf8e 之间的 commits 的 patch 文件:
(注意 af8e2 比 eaf8e 早)
git format-patch af8e2..eaf8e
合并 format-patch 命令生成的 patch 文件:
git am 0001-Update.patch
与 git apply
不同,这会直接 add 和 commit。
只下载最新代码
git clone --depth 1 git://xxxxxx
这样 clone 出来的仓库会是一个 shallow 的状态,要让它变成一个完整的版本:
git fetch --unshallow
或
git pull --unshallow
基于某次 commit 创建分支
git checkout -b test 5234ab
表示以 commit hash 为 5234ab
的代码为基础创建分支 test
。
恢复单个文件到指定版本
git reset 5234ab MainActivity.java
恢复 MainActivity.java 文件到 commit hash 为 5234ab
时的状态。
设置全局 hooks
git config --global core.hooksPath C:/Users/mazhuang/git-hooks
然后把对应的 hooks 文件放在最后一个参数指定的目录即可。
比如想要设置在 commit 之前如果检测到没有从服务器同步则不允许 commit,那在以上目录下建立文件 pre-commit,内容如下:
#!/bin/sh
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
git fetch origin $CURRENT_BRANCH
HEAD=$(git rev-parse HEAD)
FETCH_HEAD=$(git rev-parse FETCH_HEAD)
if [ "$FETCH_HEAD" = "$HEAD" ];
then
echo "Pre-commit check passed"
exit 0
fi
echo "Error: you need to update from remote first"
exit 1
查看某次 commit 的修改内容
git show <commit-hash-id>
查看某个文件的修改历史
git log -p <filename>
查看最近两次的修改内容
git log -p -2
应用已存在的某次更改
git cherry-pick <commit-hash-id>
cherry-pick 有更多详细的用法,可以参见帮助文档。
命令行自动补全
在 shell 里加载 git-completion 系列脚本,详见 https://github.com/git/git/tree/master/contrib/completion
文件每一行变更明细
git blame <filename>
找回曾经的历史
git reflog
列出 HEAD 曾指向过的一系列 commit,它们只存在于本机,不是版本仓库的一部分。
还有:
git fsck
以上是关于Git的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段15——git命令操作一个完整流程
GitGit 分支管理 ( 克隆远程分支 | 克隆 master 分支 git clone | 查看远程分支 git branch -a | 克隆远程分支 git checkout -b )(代码片段
GitGit 分支管理 ( 克隆远程分支 | 克隆 master 分支 git clone | 查看远程分支 git branch -a | 克隆远程分支 git checkout -b )(代码片段