Git使用笔记
原文链接 https://lingxiankong.github.io/2014-07-18-git-notes.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
配置
git config --list
查看系统变量的配置
export https_proxy="http://XXXXXX:XXXXXX@XXXXXX:8080/" 配置代理
密码中的特殊字符转义:
ampersand & (%26)
at @ (%40)
space (%20)
double-quote " (%22)
single-quote ' (%27)
colon : (%3A)
git config --global core.editor "vim"
修改默认编辑器,如果是仅修改当前repo的配置,删除global即可。
删除文件
1、手动删除
2、git rm [filename] (如果要删除之前修改过且已暂存的文件,要加-f)
3、提交
从暂存中移除,但不删除文件:git rm --cached readme.txt
取消暂存:git reset HEAD readme.txt
放弃未暂存文件所做的修改:git checkout -- readme.txt
文件重命名
git mv [file_from] [file_to]
,相当于:
$ mv README.txt README
$ git rm README.txt
$ git add README
忽略文件
在projec目录下:
$ cat .gitignore
*.[oa]
!lib.a
temp/
如果文件已经暂存,不会立即使用gitignore的新规则,此时先用git rm --cached filename
也可使用全局的.gitignore文件来对所有的代码库生效,比如新建文件~/.gitignore_global
,然后执行:
git config --global core.excludesfile ~/.gitignore_global
全局忽略只能忽略那些原来没有被track的文件,如果已经纳入了版本管理,修改.gitignore也是无效的。
相关知识可以参见:https://segmentfault.com/q/1010000000430426
日志查看搜索
git log -p展开显示提交的内容差异;-2显示最近两条;--stat
,仅显示简要的增改行数统计;
git log --pretty=oneline --no-merges
每个提交放在一行显示,不显示merge的记录
git log --graph --oneline --all
git log --graph --oneline --decorate
可以以图形化的方式显示branch关系
git log --since=2.weeks
查看两周内提交记录,或类似于--since="2008-10-01" --before="2008-11-01"
--author --committer
图形化工具:gitk
根据commit消息搜索:git log --grep="Something in the message"
搜索内容第一次出现或删除的提交:git log -S "TODO: Check for admin status"
按文件搜索:git log lib/foo.rb
标签
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
git show v1.2
查看tag信息
git tag v1.4.0
增加一个轻量tag
为先前的提交加tag:
1、git log --pretty=oneline
2、git tag -a v1.2 9fceb02 -m 'my version 1.4'
(这是一个含附注tag,标签的签署不讲了,google吧)
推送tag到远端仓库:git push origin v1.2
一次性推送所有tag:git push origin --tags
远程仓库
git remote -v 查看远程仓库和克隆地址
git remote add [shortname] [url]
添加一个远程仓库
git remote show [remote-name]
显示远端仓库的详细信息
git remote rename [old_name] [new_name]
修改远端仓库在本地的简称
git remote rm [remote-name]
移除远端仓库
git fetch [repo] [branch]
抓取远程仓库的更新,但不合并(克隆操作会自动使用默认的 master 和 origin 名字)
git fetch origin branch1:branch2
使用远程branch1分支在本地创建branch2(但不会切换到该分支), 如果本地不存在branch2分支, 则会自动创建一个新的branch2分支, 如果本地存在branch2分支, 并且是`fast forward', 则自动合并两个分支, 否则, 会阻止以上操作
git pull [repo] [branch]
将远端分支自动合并到本地仓库中当前分支
git push [remote-name] [branch-name]
将本地仓库中的数据推送到远程仓库,一个示例(将本地分支提交到远程仓库的另一个分支):git push origin localbranch:remotebranch
分支
git checkout -b [分支名] [远程名]/[分支名]
创建分支(-d 删除分支,-D 强制删除)
删除远程服务器上的分支:git push origin :[remote_branch]
git merge --no-ff myfeature
--no-ff
标记会使合并永远创建一个新的commit对象,在新的分支中保留myfeature分支的merge记录。
找到dev分支在master分支上的commitID:
git merge-base dev master
会显示dev和master两个分支的共同的commitID
Git References 介绍:https://git-scm.com/book/en/v2/Git-Internals-Git-References
- 在
.git/refs
目录下 git 维护了一些 commit id 的映射,git update-ref
可以修改映射关系,比如:git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
.git/HEAD
总是指向当前 branch,其实它的内容是指向其他的 ref,可以使用命令设置:git symbolic-ref HEAD refs/heads/test
部分提交
比如为了fix 2个bug 修改同一个文件,但想分开提交。可以使用交互式 add:
git add -p [file_name]
根据提示进行选择(这里选择s对要提交的内容进行分割):
输入 y 暂存块
输入 n 不暂存块
输入 e 手动编辑块
输入 d 退出或者跳转到下一个文件
输入 s 分割块
合并提交
比如想合并最后的两次提交,可以使用:
git rebase -i HEAD~2
与git add -p一样是交互式操作,它将询问你想要合并哪些提交。你pick(拣选)最近的提交然后squash(合并)旧的提交。
另一种场景是:如果你正并行工作在两个或者更多的分支上,你也许会发现一个存在于所有分支上的bug。如果你解决了一个分支上的这个bug,你可以拣选这个对应的提交应用到其他分支上,而不会弄乱其他文件或者提交。
在要应用bugfix的分支上执行:git cherry-pick [已解决bug分支的commit_hash]
储藏
https://git-scm.com/docs/git-stash
当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做手头的工作, 那么就可以用 git stash 来保存当前的工作状态, 等你修复完bug后, 再回到之前的工作里.
$ git stash save "work in progress for foo feature"
$ git stash list
$ git stash apply stash@{0}
$ git stash drop stash@{0}
补丁
git diff 查看尚未暂存的文件更新了哪些部分
git diff --cached
查看已经暂存起来的文件和上次提交之间的差异
git format-patch
生成的补丁,是git专用的,也是日常工作中最常接触到的补丁类型,为每个提交生成一个 .patch 后缀的 mbox 文件,包含了提交的附加信息:比如作者,时间等。在此基础上使用git am
命令即可将此补丁应用到当前分支。注意应用完之后,你会发现当前分支多了一次提交记录,并且有完整的信息,而不是简单的修改文件。
git format-patch master 获取所有dev分支在master分支基础上的patch文件
git format-patch HEAD^ 有几个^就会打几个patch,从最近一次打起
或者是git format-patch -1
以及git format-patch -2
应用补丁:
1、对于git diff命令生成的补丁文件,使用git apply,是事务性操作,比patch命令严谨很多 ,可以先用git apply --check查看补丁是否能够干净顺利地应用到当前分支;
2、对于format-patch生成的补丁,使用git am,自动创建提交对象,如果出现冲突:
$ (fix the file)
$ git add file
$ git am --resolved
回退
有几个概念:
working directory: 工作区,文件被修改后,add前就在这个区域;
index:文件被add之后在这个区域;
未提交
撤销所有修改,使工作目录回到上次提交后的状态:
git reset --hard HEAD
这个命令会把你工作目录中所有未提交的内容清空(但不包括 untracked files,比如新增的文件,要使用git clean). 从另一种角度来说, 这会让"git diff" 和"git diff --cached"命令的显示都变为空.
如果是回退一个文件:git checkout -- hello.py
如果想使工作目录跟 upstream 上 master 保持一致:git reset --hard origin/master
git reset用法
git reset [--hard|soft|mixed|merge|keep] [commit或HEAD]
根据--soft --mixed --hard
,会对working directory、index、HEAD进行重置。
A). --hard
:除了“Untracked files”,其他变更都被重置。即:重设index和working directory,自从commit以来在working directory和index中的任何改变都被丢弃,并把HEAD指向commit。
B). --soft
:这个模式的效果是,执行完毕后,自从commit以来的所有改变都会显示在git status的"Changes to be committed"中,当然,还有“Untracked files”。即:恢复commit以来的index和working directory内容。即:not commited
C). --mixed
:这个模式是默认模式,一般情况下够用。这个模式的效果是,自从commit以来的修改都会被保留,但会被标记成"Changes not staged for commit"。即:仅重置index,文件修改被转移到working directory中。即:not added
如何使用 reset 之前的 commit message 呢:
$ git commit ...
$ git reset --soft HEAD^ (1)
$ edit (2)
$ git commit -a -c ORIG_HEAD (3)
(1) 当提交了之后,你又发现代码没有提交完整,或者你想重新编辑一下提交的comment,执行git reset --soft HEAD^,让working tree还跟reset之前一样,不作任何改变。HEAD^指向HEAD之前最近的一次commit。
(2) 对working tree下的文件做修改
(3) 然后使用reset之前那次commit的注释、作者、日期等信息重新提交。注意,当执行git reset命令时,git会把老的HEAD拷贝到文件.git/ORIG_HEAD
中,在命令中可以使用ORIG_HEAD引用这个commit。commit 命令中 -a 参数的意思是告诉git,自动把所有修改的和删除的文件都放进stage area,未被git跟踪的新建的文件不受影响。commit命令中-c commit
或者 -C commit
意思是拿已经提交的commit对象中的信息(作者,提交者,注释,时间戳等)提交,那么这条commit命令的意思就非常清晰了,把所有更改的文件加入stage area,并使用上次的提交信息重新提交。
已提交
1、创建新的commit修复错误
撤消(revert),其实对于revert的操作我用的很少,也不太明白revert的使用场景,等后续用得多了,再来补充.
2、修改提交来修复错误
就是常用的git commit --amend
了,但如果错误的使用了 amend(原本是想独立的commit) 该如何恢复?
git reset --soft @{1}
,同时可以用git commit --reuse-message @{1}
或git commit -C @{1}
拿到刚刚的commit message。这里有详细的解释,@{1}
意思是 where currentbranch pointed one step ago
技巧
有时上传一些大文件(比如图片),会出现fatal: The remote end hung up unexpectedly的提示,这是由于git/https的缓冲设置导致,可以通过如下方式解决:
git config http.postBuffer 524288000
使用github时,在git push往往会对用户名和密码进行认证,每次的输入很烦躁,效率很低。如果已经上传了本机的ssh公钥到github,那么可以配置项目目录下的.git/config
文件:
remote.origin.url=git@github.com:{username}/{projectname}.git
比如我这里就是:url = git@github.com:LingxianKong/lingxiankong.github.io.git