[TOC]
master: 默认开发分支
origin: 默认远程版本库
Index / Stage:暂存区
Workspace:工作区
Repository:仓库区(或本地仓库)
Remote:远程仓库
git clone
git config --global user.name "kingreatwill"
git config --global user.email "350840291@qq.com"
ssh-keygen -t rsa -C "350840291@qq.com"
配置存放在.gitconfig文件中
# 显示当前的Git配置
$ git config --list
# 编辑Git配置文件
$ git config -e [--global]
git remote -v
git remote add shortname url # 添加远程仓库
git remote add origin git@github.com:xxx/learngit.git
git remote rm origin:删除已有的远程仓库;
git fetch shortname #从远程仓库中获得数据,
git remote show origin #查看某个远程仓库
git remote rename origin new_origin #重命名
git remote rm paul #删除
# 下载远程仓库的所有变动
$ git fetch [remote]
# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]
# 上传本地指定分支到远程仓库
$ git push [remote] [branch]
# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force
# 推送所有分支到远程仓库
$ git push [remote] --all
# 删除远程分支或标签
$ git push <remote> :<branch/tag-name>
# 上传所有标签
$ git push --tags
# 查看状态
$ git status
# 查看变更内容
$ git diff
# 添加指定文件到暂存区
$ 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 --work-tree=E:/xxx --git-dir=E:/xxx/.git pull
git -C "E:/xxx" pull
git checkout .
或者指定文件 git checkout -- filename
git reset --hard commitidxxx
然后git push -f
强制推送, 那么之前的提交会丢弃git revert -n commitidxxx
然后git commit -m "xxx"
,最后git push
$ git reset HEAD^ # 回退所有内容到上一个版本
$ git reset HEAD^ hello.php # 回退 hello.php 文件的版本到上一个版本
--hard 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交:git reset --hard HEAD
还原工作区(文件内容)
git checkout – <file_name> 丢弃工作区的修改,并用最近一次的commit内容还原到当前工作区(对文件中内容的操作,无法对添加文件、删除文件起作用)
git checkout HEAD^ – <file_name> 将指定commit提交的内容(HEAD^表示上一个版本)还原到当前工作区
git checkout <branch_name> – <file_name> 将指定分支的指定提交内容还原到当前分支工作区
git restore 用法总结
git restore --staged <file_name> 将暂存区的修改重新放回工作区(包括对文件自身的操作,如添加文件、删除文件)
git restore <file_name> 丢弃工作区的修改(不包括对文件自身的操作,如添加文件、删除文件)
Git恢复之前版本的两种方法reset、revert(图文详解)
一次搞清 git checkout,git restore 和 git reset
创建一个新仓库
# 在当前目录新建一个Git代码库
$ git init
# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]
# 下载一个项目和它的整个代码历史
$ git clone [url]
git clone git@codechina.csdn.net:kingreatwill/open.git
cd open
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
cd existing_folder
git init
git remote add origin git@codechina.csdn.net:kingreatwill/open.git
git add .
git commit -m "Initial commit"
git push -u origin master
git add xx
命令可以将xx文件添加到暂存区,如果有很多改动可以通过
git add -A .
来一次添加所有改变的文件。
注意 -A
选项后面还有一个句点。
git add -A
表示添加所有内容,
git add .
表示添加新文件和编辑过的文件不包括删除的文件;
git add -u
表示添加编辑或者删除的文件,不包括新添加的文件
git clone https://git.coding.net/gamedaybyday/HelloGit.git D:\Git\HelloGit
git pull https://zhangsan:123456@github.com
git clone 带用户名密码的形式但包含@等特殊符号无法正常解析
正常使用git clone 的方式
git clone https://remote
使用带用户名密码的方式(可以避免后续每次都要输入用户名密码)
git clone https://[username]:[password]@/remote
但有时会出现用户名或密码中含有像@这样的特殊符号,而不能被正常解析
我们需要通过下面方式进行重新编码
String c = URLEncoder.encode("@","utf-8");
System.out.println(c);
console -> %40
所有这样就可以知道@在url中需要写成%40的形式
推送现有的 Git 仓库
cd existing_repo
git remote rename origin old-origin
git remote add origin git@codechina.csdn.net:kingreatwill/open.git
git push -u origin --all
git push -u origin --tags
git log --name-status #每次修改的文件列表, 显示状态
git log --name-only #每次修改的文件列表
git log --name-only -1 #查看最近一次提交的文件列表
git log --stat #每次修改的文件列表, 及文件修改的统计
git log --pretty=format:"" -1 # --pretty=format:"" 格式化commit message 这里什么都不显示
git log --pretty=format:"" --name-only -1 # --pretty=format:"" 格式化commit message 这里什么都不显示
git whatchanged #每次修改的文件列表
git whatchanged --stat #每次修改的文件列表, 及文件修改的统计
git show #显示最后一次的文件改变的具体内容
git show -5 #显示最后 5 次的文件改变的具体内容
git show <commit-id> #显示某个 commitid 改变的具体内容
git show --name-only #显示最后一次的文件列表
git show --pretty=format:"" --name-only #显示最后一次的文件列表 # --pretty=format:"" 格式化commit message 这里什么都不显示
git show --pretty=format:"" --name-only <commit-id> #显示某个 commitid 的文件列表
git diff --name-only <commit-id-1> <commit-id-2> #比较两次commit修改的文件列表
git push [remote-name] [branchname]。
git push -u origin master:由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
git push origin master
git push origin tagname:推送某个标签到远程
git push origin --tags:一次性推送全部尚未推送到远程的本地标签
git init
git add file/directory
git add -A 添加所有
git commit -m <注释>
git commit 加上 -a 跳过 git add 步骤
git commit -a -m 'added new benchmarks'
git commit --amend #撤消提交
例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终你只会有一个提交——第二次提交将代替第一次提交的结果。
git status # git status -s :--short
git diff
git branch google #创建分支
git checkout google # 切换分支
git checkout -b google # 创建并切换
git push origin newbranch # 推送本地分支到远程分支(远程没有会自动创建)
git push origin newbranch:newbranch # 推送本地分支到远程分支(远程没有会自动创建,:前面的是本地分支,:后面是远程分支)
git branch -d xx # 删除本地分支
git pull origin dev # 拉取远程分支到本地
有时在远程创建的分支本地没有:
git branch -a # 查看所有分支
git fetch --all # 拉取所有
git checkout -b 0.1 origin/0.1 # 拉取远程分支0.1 并创建本地分支0.1
git branch --set-upstream-to origin/0.1 # 关联本地当前分支到远程分支
# 显示所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-namel
$ git branch -dr [remote/branch]
# 新建一个分支,并切换到该分支
$ git checkout -b [branch]
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 衍合指定分支到当前分支
$ git rebase <branch>
# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]
git rm
git checkout -b dev:git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
git branch dev
git checkout dev
git push origin dev # 推送本地分支到远程分支(远程没有会自动创建)
git branch:查看当前分支,git branch命令会列出所有分支,当前分支前面会标一个*号。
git branch -d dev:删除dev分支了
git merge
git merge dev:git merge命令用于合并指定分支到当前分支。
git tag:查看所有标签
git tag -a v1.4 -m "my version 1.4" # 附注标签(annotated)
git tag v1.4-lw #轻量标签(lightweight)
git tag v1.0:在当前分支的HEAD上打标签
git tag v0.9 f52c633:#后期打标签,在当前分支的指定commit上打标签
git tag -a v0.9 f52c633
git tag -d v0.1:删除指定标签
git tag -l 'v1.8.5*' #只对 1.8.5系列感兴趣
git show v1.4
git push origin v1.4
git push origin --tags:一次性推送全部尚未推送到远程的本地标签
git checkout v1.4
# 列出所有本地标签
$ git tag
# 基于最新提交创建标签
$ git tag <tagname>
# 删除标签
$ git tag -d <tagname>
# 删除远程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 log:提交历史
git log --pretty=oneline
git log --pretty=format:"%h - %an, %ar : %s"
另外一个常用的选项是 --pretty。 这个选项可以指定使用不同于默认格式的方式展示提交历史。 这个选项有一些内建的子选项供你使用。 比如用 oneline 将每个提交放在一行显示,查看的提交数很大时非常有用。 另外还有 short,full 和 fuller 可以用,展示的信息或多或少有些不同,请自己动手实践一下看看效果如何。但最有意思的是 format,可以定制要显示的记录格式。 这样的输出对后期提取分析格外有用 — 因为你知道输出的格式不会随着 Git 的更新而发生改变:
git log --pretty=format 常用的选项
选项 | 说明 |
---|---|
%H | 提交对象(commit)的完整哈希字串 |
%h | 提交对象的简短哈希字串 |
%T | 树对象(tree)的完整哈希字串 |
%t | 树对象的简短哈希字串 |
%P | 父对象(parent)的完整哈希字串 |
%p | 父对象的简短哈希字串 |
%an | 作者(author)的名字 |
%ae | 作者的电子邮件地址 |
%ad | 作者修订日期(可以用 --date= 选项定制格式) |
%ar | 作者修订日期,按多久以前的方式显示 |
%cn | 提交者(committer)的名字 |
%ce | 提交者的电子邮件地址 |
%cd | 提交日期 |
%cr | 提交日期,按多久以前的方式显示 |
%s | 提交说明 |
你一定奇怪 作者 和 提交者 之间究竟有何差别, 其实作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人。 所以,当你为某个项目发布补丁,然后某个核心成员将你的补丁并入项目时,你就是作者,而那个核心成员就是提交者。 |
git log --graph:可以看到分支合并图。
git log --pretty=format:"%h %s" --graph
git log -p -2
一个常用的选项是 -p,用来显示每次提交的内容差异。 你也可以加上 -2 来仅显示最近两次提交
git log --stat
如果你想看到每次提交的简略的统计信息,你可以使用 --stat 选项
git log 的常用选项
选项 | 说明 |
---|---|
-p | 按补丁格式显示每个更新之间的差异。 |
--stat | 显示每次更新的文件修改统计信息。 |
--shortstat | 只显示 --stat 中最后的行数修改添加移除统计。 |
--name-only | 仅在提交信息后显示已修改的文件清单。 |
--name-status | 显示新增、修改、删除的文件清单。 |
--abbrev-commit | 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。 |
--relative-date | 使用较短的相对时间显示(比如,“2 weeks ago”)。 |
--graph | 显示 ASCII 图形表示的分支合并历史。 |
--pretty | 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 |
format(后跟指定格式)。 |
# see the changes of a file, works even
# if the file was deleted
git log --full-history -- x\xx\.gitkeep
# limit the output of Git log to the
# last commit, i.e. the commit which delete the file
# -1 to see only the last commit
# use 2 to see the last 2 commits etc
git log --full-history -1 -- x\xx\.gitkeep
# include stat parameter to see
# some statics, e.g., how many files were
# deleted
git log --full-history -1 --stat -- x\xx\.gitkeep
# 获取 git 仓库中所有文件的最新修改时间
$ git ls-tree -r --name-only HEAD | while read filename; do
> echo "$(git log -1 --pretty=format:"%ad" -- $filename) $filename";
> done
# 获取 git 仓库中所有文件的最初创建时间
$ git ls-tree -r --name-only HEAD | while read filename; do
> echo "$(git log --pretty=format:"%ad" -- $filename | tail -1) $filename";
> done
How to retrieve the last modification date of all files in a Git repository
Finding the date/time a file was first added to a Git repository
# 撤销工作目录中所有未提交文件的修改内容
$ git reset --hard HEAD
# 撤销指定的未提交文件的修改内容
$ git checkout HEAD <file>
# 撤销指定的提交
$ git revert <commit>
# 退回到之前1天的版本
$ git log --before="1 days"
# 恢复暂存区的指定文件到工作区
$ 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的过程中,由于操作不当,作为初学者的我们可能经常要去解决冲突。某些时候,当你不小心改错了内容,或者错误地提交了某些commit,我们就需要进行版本的回退。版本回退最常用的命令包括git reset和git revert。这两个命令允许我们在版本的历史之间穿梭。
下面就几种比较经典的场景进行总结:
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本;要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
git reset HEAD~3 #当前分支相当于回滚了3个提交点,HEAD^ 一个 HEAD^^ 两个
git reset --hard HEAD^
git reset --hard 1094a
git reset HEAD :git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
reset有3种常用的模式:
git reflog:命令历史
git checkout
git checkout -- file:撤消对文件的修改:丢弃工作区的修改,让这个文件回到最近一次git commit或git add时的状态。命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令。
Git revert用来撤销某次操作,此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交。git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容。
Git revert和git reset都可以进行版本的回退,将工作区回退到历史的某个状态,二者有如下的区别:
https://blog.csdn.net/yxlshk/article/details/79944535
https://git-scm.com/docs/git-revert
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_NAME" = "kingreatwill" ];
then
GIT_AUTHOR_NAME="wcoder";
GIT_AUTHOR_EMAIL="350840291@qq.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
用户名为kingreatwill的提交记录,将该提交记录的用户名和邮箱修改为wcoder和350840291@qq.com。
清除缓存即可再次执行git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch Rakefile' HEAD
修改最近一次的信息:git commit --amend --author="程序员小富 <515361725@qq.com>" --no-edit
Git stash用来暂存当前正在进行的工作, 将工作区还没加入索引库的内容压入本地的Git栈中,在需要应用的时候再弹出来。比如想pull 最新代码,又不想加新commit;或者为了修复一个紧急的bug,先stash,使返回到自己上一个commit,改完bug之后再stash pop,继续原来的工作。Git stash可以让本地仓库返回到上一个提交状态,而本地的还未提交的内容则被压入Git栈。Git stash的基本使用流程如下:
git stash #暂存工作区尚未提交的内容
Do your work #在上一个提交的状态之上完成你的操作
git stash pop #将暂存的内容弹出并应用
当你多次使用git stash命令后,你的栈里将充满了未提交的代码,这时候你会对将哪个版本应用回来有些困惑,
这时git stash list命令可以将当前的Git栈信息打印出来,你只需要将找到对应的版本号,
例如使用 git stash apply stash@{1} 就可以将你指定版本号为stash@{1}的暂存内容取出来,当你将所有的栈都应用回来的时候,可以使用git stash clear来将栈清空。TortoiseGit中的stash save菜单就对应该命令。
https://git-scm.com/docs/git-stash
https://git-scm.com/docs/git-merge
# 合并指定分支到当前分支
$ git merge [branch]
在rebase的过程中,也许会出现冲突。在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用git add命令去更新这些内容的索引, 然后,你无需执行git-commit,只要执行git rebase –continue,这样git会继续应用(apply)余下的补丁。如果要舍弃本次衍合,只需要git rebase --abort即可。切记,一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行rebase操作。
我们在使用git pull命令的时候,可以使用--rebase参数,即git pull --rebase。这里表示把你的本地当前分支里的每个提交取消掉,并且把它们临时保存为补丁(这些补丁放到.git/rebase目录中),然后把本地当前分支更新为最新的origin分支,最后把保存的这些补丁应用到本地当前分支上。在使用tortoise的pull的过程中,如果你留意tortoiseGit的日志的话,你就会发现,它使用的就是这种方式来pull最新的提交的。
git blame -L 50,50 init/main.c
git cherry-pick commitID
https://www.cnblogs.com/yychuyu/p/13751649.html
git gc [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune] [--force]
1、简单指令:
git gc
2、 --aggressive:仔细检查并清理,犹如电脑的全部杀毒,用时较久,一般上100个commit后可以执行,经常执行区别不大:
git gc --aggressive
3、 --auto:大概看一下仓库有没有需要整理,如果情况良好,不执行gc:
git gc --auto
4、—no-prune:不要整理任何零散的文件:
git gc -no-prune
5、–quiet:取消所有进度报告:
git gc --quiet
运行git prune命令即可,或者直接运行git gc --prune=now把所有的悬空对象都清空
git gc --prune=now
找出大文件
git rev-list --objects --all | grep -a "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print $1}')"
删除文件
删文件,将 bigfile 换成上面找出的文件名
git filter-branch --force --index-filter
'git rm --cached --ignore-unmatch "bigfile"'
--prune-empty -- --all
删文件夹,将 wrongdir 换成上面找出的文件夹
git filter-branch --force --index-filter
'git rm -r --cached --ignore-unmatch "wrongdir"'
--prune-empty -- --all
git push --force --verbose --dry-run
git push --force
git rev-list --objects --all | grep -E `git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}' | sed ':a;N;$!ba;s/\n/|/g'`
或
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -15 | awk '{print$1}')"
注意:下方命令中的 path/to/large/files 是大文件所在的路径,千万不要弄错!
git filter-branch --tree-filter 'rm -f path/to/large/files' --tag-name-filter cat -- --all
git push origin --tags --force
git push origin --all --force
如果在 git filter-branch
操作过程中遇到如下提示,需要在 git filter-branch
后面加上参数 -f
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
并告知所有组员,push 代码前需要 pull rebase,而不是 merge,否则会从该组员的本地仓库再次引入到远程库中,导致仓库在此被 Gitee 系统屏蔽。
更加具体的操作可以点击文章 改写历史,永久删除git库的物理文件 查看
突破GitHub的限制,使用 git-lfs(Git Large File Storage) 支持单个文件超过100M
git lfs install
git lfs track "*.pdf"
and git lfs track "*.ppt"
对这些大文件(默认10M)在git的repository里面只存一个小的文本文件,这个文本文件描述了要去哪里下载对应的二进制文件。
github限制LFS的存储大小(全部仓库)是1GB,超过后需要付费;
如果你已经删除后仍然无法使用LFS,请联系官方客服:developer@githubsupport.com
使用注册Github的邮箱账号发送邮件,用英语提供必要信息:账号、描述问题、截图
生成一个可供发布的压缩包