Git快速参考

魔法师LQ

Git进行版本控制,管理的是修改而非文件。
分清楚工作区,版本库,暂存区(stage)就能很好地理解其工作原理。

基本概念

工作区(Working Directory):顾名思义是工作的地方,对文件的创建,修改,添加,删除等都会对其造成影响。比方说我创建的一个项目工程就是一个工作区。
版本库(Repository):工作区中有一个隐藏的目录.git,不算工作区而是Git版本库。
Git版本库最终的就是stage(或者叫index)的暂存区,还有Git默认创建的master分支,以及指向master分支的HEAD指针。
文件的增删变更直接作用在工作区,第一步,变更后add,就添加到了版本库的暂存区。
第二步,git commit提交更改,就是将暂存区的所有内容提交到当前分支。
简单的理解就是,需要提交的文件修改都放在暂存区,然后一次性提交暂存区中的内容到到当前分支。

文件修改和“时光穿梭”

  • 场景1:当修改了工作区的文件内容,觉得不合适,想直接丢弃工作区的修改,使用命令:git checkout -- filenname
  • 场景2:当修改了工作区的文件内容,觉得不合适,但是已经通过git add添加修改到了暂存区,想直接丢弃工作区的修改,分两步,第一步,使用命令git reset HEAD filename,就回到了场景1;第二步按照场景1来操作。
  • 场景3:已经通过git commit提交了不合适的修改到版本库中,想要撤销本次提交,就执行版本退回命令,git reset --hard commid_id进行时光穿梭。穿梭前可以使用git log查看历史版本;当还需要重返未来的时候,使用git reflog查看历史命令。

删除文件

使用rm filename来在工作区删除文件,现在工作区和版本库就不一致了。

  • 场景1:确认删除该文件,使用git rm filename命令,然后git commit
  • 场景2:属于误删操作,但是还没有提交到版本库,使用命令git checkout -- filename,使用版本库中的版本替换到工作区的版本。
  • 场景3:已经提交到版本库,发现属于误删操作,执行版本回退来时光穿梭。

分支管理

  • 创建和切换分支:git checkout -b branch_name.相当于两句指令:git branch branch_name, 随后git checkout branch_name

ps: 关于Vim重命名文件,在退出之前输入:sav new_file_name即可,会保存一个相同内容的副本,而不是在当前修改文件中修改,要想这样需要安装特定的插件。

  • 查看分支:git branch
  • 创建分支:git branch <branch_name>
  • 切换到分支:git checkout <branch_name>
  • 创建加切换:git checkout -b <branch_name>
  • 合并到当前:git merge <branch_name>
  • 删除分支:git branch -d <branch_name>

冲突解决

新建分支在上面修改后,add, commit,然后切换到要汇入的分支上,假如此时在当前分支上也做了修改,执行git merge <branch_to_be_merged>时发现无法合并,使用git status查看冲突位置,然后修改冲突(就是文件中标注的位置,通常就是同一行内容不一致导致的),修改完毕后重新add,commit,以及merge就行了。
可以使用git log --graph <--abbrev-comit> 查看分支合并情况图

分支管理策略

通常合并分支使用的都是Fast forward模式,在合并的时候加上--no-ff参数就可以采用普通模式合并,历史记录中会有分支的信息,而Fast forward在合并后删除分支日志历史中就没有关于此分支的记录,也就看不出来曾经做过合并。

保存和恢复现场

场景:当手头正在多某项工作,突然接到任务需要马上处理,手头的工作不得不停下,但是还没有完善到能够提交的程度。该怎么办?
相当于打断点,保存现场,使用git stach保存当前的工作。然后去处理临时或者紧急的任务(比如说修复某个bug)。当临时或者紧急任务处理完毕后,返回来恢复现场继续原来的工作。
恢复现场使用,git stash list查看有哪些存档,然后使用git stash apply <stash@{xxx}>来恢复,参数是可选的用于多次stash之后选择要恢复的那个。这种方式恢复后stash的内容不删除,需要输入git stash drop来删除。
另一种方式能够恢复的同时删除stash,即使用git stash pop

删除未合并过的分支

场景:导师给了个新需求要做,做完了却悲催地听说不需要了,现在要删除这个分支。git brach -d <feature>,会提示The branch '<feature>' is note fully merged. If you are sure you want to delete it , run'git branch -D <feature>'

所以git branch -D <branch_name>就是强制删除未曾合并过的分支的命令。

远程分支操作

  • 场景1:在本地创建了一个分支,但是远程没有,commit之后希望push到远程比方说Github上,但是不是master分支,而是一个目前还没有创建的分支上。使用git push -u origin <local_branch_name>,这样就在远程创建了和local_branch_name同名分支。
  • 场景2:远端已经存在和本地同名或者不同名的分支,希望这时将本地的分支推到远端上,git push <remote_name> <local_branch_name>:<remote_branch_name>

  • 场景3:当有多人同时提交到一个分支,自己的提交和他人的有冲突,这时按照提交的提示来做,一般会提示git pull ...,将远程的提交pul下来。pull下来后再次提交,若发现push有冲突,则需要手动解决冲突,解决方法和上文的冲突解决一致。解决后再进行push即可。

  • 场景4:远程已经存在某个分支,想在本地创建一个分支和远程的分支对应起来。使用git checkout -b local_branch_name origin/remote_branch_name
  • 场景5:远程已经存在某个分支,本地同时存在某个分支,现在要把两个关联起来,使用git branch --set-upstream-to=origin/remote_branch_name local_branch_name,制定本地分支和远程分支的关联。这样就能解决某些时候pull失败的问题,比如no tracking information

rebase整理push历史

  • 场景:本地版本历史过多,有的commit并没有push到远程,所以再查看历史的时候希望只查看push过的提交,使用git rebase命令实现。

tag

为commit打上标签

  • 场景1:某个工作已经进行了多次的编辑和提交。过了一阵子,导师或者其他人说,请把之前的某次提交打包一下。这时选择查找commit_id显得就不是很方便。tag就相当于是对于commit的起的别名,使用git tag <tag_name>默认为最近的一次提交打上标签,在产看log的时候,就会出现相应的标签提示。使用git show tag_name来查看tag_name对应的那次提交。

  • 场景2:之前的提交忘记打标签,现在需要对历史中某个版本打上标签。使用git tag tag_name commit_id。使用git tag查看所有标签。

  • 场景3:创建某个标签的同时,还提供一些说明信息。使用git tag -a tag_name -m "balala enengy... commit_id。使用git show tag_name就能查看到相应说明文字。

标签操作

  • 场景1,打错了,在本地删除:git tag -d tag_name
  • 场景2,推送某次提交的标签到远程:git push origin tag_name
  • 场景3,推送全部尚未推送到远程的标签:git push origin --tags
  • 场景4,删除远程的标签:先要删除本地的要删除的标签。然后执行,git push origin :refs/tags/tag_name,然后去远程查看标签是否被删除。

自定义Git

除了配置user.name, user.email之外还可以配置一些东西。

  • 场景,命令行工作颜色单调:配置显示ui, git config --global color.ui true,使文件名也被不同的颜色标注。(我使用git bash本身就是有颜色的)。

设置忽略规则

这个功能非常有必要,特别是在一些项目中有比较大或者涉及敏感信息的文件时(比如密码,很大很大的数据集等)。编写.gitignore文件来屏蔽某些类型的文件。文件每行表示一个屏蔽规则,一个规则可以屏蔽某个具体的文件或者某一类或几类文件的提交。可以使用通配符来编写规则,#作为注释。

1
2
3
4
5
# 要忽略提交什么文件
file_name
*.dat
*.py[cod]
db.ini

  • 当发现某个在屏蔽规则中文件恰好必须要提交上去,使用git add -f file_name.file_type
  • 使用git check-ignore来检查屏蔽规则

配置命令别名

  • 通常使用缩写来给某个长的命令或者组合当做别名,来提高生产效率。使用git config --global alias.s_name 'long_command_name',比如:git config --global alias.br branch,就可以使用git br代替git branch操作了。

例如:

git config —global alias.lg “log —color —graph —pretty=format:’%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset’ —abbrev-commit”

  • 删除某个别名:别名放在隐藏文件.git/congif[alias]后,删除别名直接把对应的行删除即可。也可以在用户主目录下的隐藏文件.gitconfig中也存放了当前用户的Git配置,可以删除文件重新配置命令。

架设Git服务器

参考1
参考2

总的来说基于Linux系统,在裸Git仓库上配置协议,就能搭建成功。有相关工具来完善和方便管理,Gitosis管理公钥,使用Gitolite进行权限管理。

当然还有GitLab方便搭建私有Git仓库,进行团队管理。