Antkillerfarm Hacking V7.0

Git(一)

2018-02-21

Git

教程

https://learngitbranching.js.org

这个网站提供了一个可视化的交互式git教程。非常不错。

git实现原理

git采用如上图所示的树状结构,因此分支的速度很快。

svn本身不支持分支功能,所谓分支无非是创建一个新的副本文件夹,而这是一个代价很高的操作,而git就简单多了,增加一个指向新分支的指针即可。

https://zhuanlan.zhihu.com/p/142289703

一文讲透Git底层数据结构和原理

git常用命令

GUI工具

  • gitk:主要用于展示分支树。

安装:

sudo apt install gitk

运行:

gitk:展示当前分支

gitk --all:展示所有分支。

gitk v1.0:展示特定分支。

  • git-gui:主要用于提交文件。

安装:

sudo apt install git-gui

运行:

git gui

以上两个工具采用tk/tcl编写,都是全平台支持的。

这两个工具的作者虽然不同,但是都在自己软件中,留下了打开对方软件的快捷方式,真可谓狼狈为奸?

  • tig:一个字符式的图形界面工具。类似的还有Lazygit和gitui。

https://zhuanlan.zhihu.com/p/601987272

有了这款开源神器,Git容易多了!(git-sim)

创建版本库

git init

Git常用的撤销操作

基本状态标识

  • A- = untracked 未跟踪
  • A = tracked 已跟踪未修改
  • A+ = modified - 已修改未暂存
  • B = staged - 已暂存未提交
  • C = committed - 已提交未PUSH

各状态之间变化

  • A- -> B : git add <FILE>
  • B -> A : git restore <FILE>
  • B -> A- : git rm --cached <FILE>
  • B -> 删除不保留文件 : git rm -f <FILE>
  • A -> A- : git rm --cached <FILE>
  • A -> A+ : 修改文件
  • A+ -> A : git checkout -- <FILE>
  • A+ -> B : git add <FILE>
  • B -> A+ : git reset HEAD <FILE>
  • B -> C : git commit
  • C -> B : git reset --soft HEAD^
  • 修改最后一次提交: git commit --amend
  • 只修改内容,不改msg: git commit --amend --no-edit
  • 修改最后一次提交的author: git commit --amend --reset-author 这里直接用当前author信息替换之,所以需要在修改前,设置好author信息

暂存本地修改及恢复

如果git pull的时候,本地有修改,就需要暂存,并在git pull之后,恢复之。

git stash

git stash pop

回退和前进

回退历史版本:

git checkout

回退之后,如果不满意,就需要前进操作,以恢复后续的更新。然而这个时候有个麻烦的地方,在git log中已经找不到后续的更新记录,也就查不到commit id。这时可以用git reflog查看git操作记录,以获得想要的commit id,并checkout之。

远程操作

查看远程仓库的地址:

有的时候时间一长,就会搞忘当初下载代码时的远程仓库的地址。这时可以使用git remote -v查看之。

查看远程分支:

git branch -r

checkout远程分支:

git checkout -b dev origin/dev

push远程分支:

git push <远程主机名> <本地分支名>:<远程分支名>

删除远程分支:

git push origin --delete dev_2

同步已经删除的远程分支:

git remote prune origin

check out有submodule的版本库

git clone --recursive URL

checkout和reset的区别

https://segmentfault.com/a/1190000006185954

git的reset和checkout的区别

制作和应用patch

制作patch主要有两种方式:git diffgit format-patch。前者生成通用patch,而后者生成git专用patch。使用示例:

git diff SHA1 SHA2 比较两个历史版本之间的差异,SHA1和SHA2是两次commit的SHA值。

git format-patch HEAD^

git format-patch -1

应用patch:git amgit apply

git apply并不会将commit message等打上去,打完patch后需要重新git addgit commit,而git am会直接将patch的所有信息打上去。

使用tag

打标签:

git tag -a v0.1.2 -m "v0.1.2"

列出标签:

git tag

检出标签:

git checkout v0.1.2

强制更新

当发生冲突,需要放弃修改,强制更新的时候,可以:

git reset --hard origin/master

保存密码

编辑仓库目录中本地的”.git/config”文件,增加如下属性:

[credential]
    helper = store

使用密码

git clone https://<USERNAME>:<PASSWORD>@github.com/path/to/repo1.git

cherry-pick

用于将分支A上的修改C,移植到分支B上。

git cherry-pick <commit id>

撤销已经push的内容

git reset --soft <SHA>

git push origin master --force

Other

git blame查看一行代码是谁改的。

HEAD表示当前版本,HEAD^^表示当前版本之前的两个版本,如果回溯的版本较多也可以写作HEAD~100

git merge -s ours branch,在不改变本地内容的情况下,触发merge操作。

如何git下载超大版本库

自从两次git完整的linux kernel,都因为网络问题,而中途失败之后,不甘心的我,继续在网上寻找答案。

目前已知的答案是git不支持断点续传,也不支持object原子下载。网上所谓的git fetch能断点续传一说,纯属误会。那只不过是重新下载的命令,即使成功,那也是由于第二次的网络环境变好导致的。

其他的办法包括git bundle,但是这个需要服务器支持才行,而多数站点都没有这个功能。Android代码的网站就采用了这种方法。

其实对付超大版本库,git已经提供了相应的办法:

git pull --depth=N

N表示深度,具体的含义我也不太清楚。基本上,N=1就是只下载当前的版本,N>1的话,还会下载以前的历史版本。这样我们可以通过不断增加N的方式,将完整的版本库下载到本地。

N增加到多大,才能把整个版本库下载完呢?

使用命令行的话,如果增加N,没有继续下载,就说明版本库已经完全下载到本地了。

如果使用TortoiseGit的话,下载完全之后,再git pull的话,就没有depth选项了。

下载失败,会在本地留下一堆无用的临时文件,可用git prune清除之。

日常使用中,git版本库更新次数越多,碎小文件越多。这时可用git gc将之打包成几个大文件。

参考文章:

http://blogs.atlassian.com/2014/05/handle-big-repositories-git/

How to handle big repositories with Git

远端仓库

查看远程仓库地址:

git remote -v

修改远程仓库地址:

git remote set-url origin URL

Github进行fork后如何与原仓库同步:

  • 添加主repo的源:

git remote add upstream URL

  • 与主repo同步:

git fetch upstream

git merge upstream/master

git push

解决server certificate verification failed问题:

git config --global http.sslverify false

gitee

gitee是github的国内山寨产品。

官网:

https://gitee.com

近来,github的国内访问速度很慢,可以使用gitee的导入功能,将代码下载到国内,然后再下载之。

Git Extensions

除了Tortoisegit之外,Git Extensions也是一个常用的GUI shell。

官网:

https://gitextensions.github.io/

.gitignore

有的文件或文件夹,你不想将它加入版本控制中,但恼人的是,每次commit的时候,这些文件都会出现在候选列表中,稍有不慎,甚至会错误选中。

这时,你可以编辑.gitignore来忽略这些文件,相当于是加了一个黑名单。但其实.gitignore也可定义白名单:

*/
!src/
!src/**

参考:

http://ybin.cc/git/gitignore-syntax/

彻底理解.gitignore

https://github.com/github/gitignore

包含各种常见开发环境的.gitignore示例

LF与CRLF转换

#提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true

#提交时转换为LF,检出时不转换
git config --global core.autocrlf input

#提交检出均不转换
git config --global core.autocrlf false

#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true

#允许提交包含混合换行符的文件
git config --global core.safecrlf false

#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

参考:

http://www.cnblogs.com/sdgf/p/6237847.html

git换行符LF与CRLF转换问题

修改用户名

git config user.name XXX

git config user.email XXX@YYY

全局配置放在~/.gitconfig,单个仓库的配置放在.git/config

下载单个文件夹

使用Git拉去github上的一些开源项目,无比方便,但是有些项目比较庞大,而我们只想拉取其中指定的一部分文件夹或者文件,那就需要我们另外动些手脚了。

1.使用SVN。

需要修改URL:

https://github.com/Sarasra/models/tree/master/research/capsules

/tree/master/换成/trunk/即可。

2.使用Sparse checkout。

git init
git remote add -f origin <url>
git config core.sparsecheckout true
echo “libs” >> .git/info/sparse-checkout

参考:

https://blog.csdn.net/deeplies/article/details/52754980

如何在github上下载单个文件夹?

https://www.zhihu.com/question/25369412

如何从GitHub上下载单个文件夹?

缺点

git对于大的二进制文件不太友好,对于文件/历史的部分导出也支持的不太好。所以对于大公司的项目来说,并不太好用。

目前的公司使用Perforce作为版本控制工具,和git相比这种老工具的功能实在是弱爆了。但是P4对于大文件支持的很好,所以还是不得不用。

参考:

http://www.ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html

谷歌的代码管理

https://www.zhihu.com/answer/175222330

代码版本控制用SVN还是Git好?

Git Server

Bonobo Git Server

一个基于IIS的Git服务器。操作简单,但是没有提供文件夹一级的权限管理。

官网:

https://bonobogitserver.com/

Gerrit

Gerrit,一种免费、开放源代码的代码审查软件,它使用Git作为底层版本控制系统。

官网:

https://www.gerritcodereview.com/

GitLab self-managed

GitLab self-managed是GitLab出品的本地Git Server。


研发人员太多的时候,还需要分布式的代码托管平台。基于GitLab生态开源组件二次开发,是其中的一种选择。

https://mp.weixin.qq.com/s/aY-QJN2Fkp86ATdvqVvpZQ

Code:美团代码托管平台的演进与实践

Fork me on GitHub