Git详解

文章目录

  • 写在篇前
  • 常用命令
      • 配置git
      • 创建代码库
      • 推送代码
      • 删除文件
      • 修改管理
      • 版本回退
      • 分支管理
      • 解决冲突
      • 标签管理
  • 其他重点
      • 登录方式
      • 关联远程库
      • 团队协作
      • 分叉直线化
      • .gitignore
      • .gitkeep
      • 注意事项
      • github-tips
  • 写在篇后

写在篇前

  Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。发明人就是大名鼎鼎的Linus ,发明初衷为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。需要知道的是Git底层文件验证采用的是SHA-1,(SHA-1)哈希算法可以被用来验证文件。哈希算法有如下特点:

  1. 不管输入数据的数据量有多大,输入同一个哈希算法,得到的加密结果长度固定
  2. 哈希算法确定,输入数据确定,输出数据能够保证不变
  3. 哈希算法确定,输入数据有变化,输出数据一定有变化,而且通常变化很大
  4. 哈希算法不可逆

常用命令

配置git

$ git config --list  # 显示当前的Git配置
$ git config -e [--global]  # 编辑Git配置文件

# 设置提交代码时的用户信息,是否加上全局--global自行决定,一般是直接设置全局的。用户邮箱,需要和你远程仓库保持一致不然你的contribution是不会被记录在远程仓库的
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"

# 常用的给命令起别名
$ git config --global alias.st status
$ git config --global alias.last 'log -1'   # 别名 显示最后一次Commit
$ 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"

  配置包括~/.gitconfig(用户级别)和.git/config(仓库级别),所有命令加上 --gloabal 就是指用户级别的配置。

创建代码库

$ mkdir project-name  # 创建目录
$ cd project-name
$ git init [project-name] # 在当前目录新建一个Git代码库
$ git clone url  # 下载项目的整个代码历史(包括各个分支提交记录等)
$ git remote add Aliases url  # 为远程库取别名,用于push/pull,如 git pull origin master
$ git remote -v # 查看远程库信息
$ git remote rm Aliases

推送代码

$ git add [* | file | dir]  # 将文件、文件夹添加到暂存区(Index)
$ git add -p  # 添加每个变化前,都会要求确认,对于同一个文件的多处变化,可以实现分次提交

$ git commit [file1 | file2] -m 'message'  # 提交暂存区到仓库区
$ git commit -a  #提交工作区自上次commit之后的变化,直接到仓库区,甚用
$ git commit -v  #提交时显示所有diff信息
$ git commit --amend -m 'message'  # 使用一次新的commit,替代上一次提交;也在代码无变化时用来修改message信息

$ git push [-u] origin master  # 提交更改到远程仓库
$ git pull origin master  # 拉取远程更改到本地仓库默认自动合并

删除文件

​   删除文件也要慎重,现在举个例子,假设我在工作区add、commit了一个文件 a.txt

  • 如果你确实想删除该文件
    • git status
    • git rm/add a.txt
    • git commit -m 'delete a.txt'
  • 如果你是误删该文件
    1. git checkout – b.txt
# 其他操作

$ git rm [file1] [file2] ...  # 删除工作区文件,并且将这次删除放入暂存区
$ git rm --cached [file]  # 停止追踪指定文件,但该文件会保留在工作区
$ git mv [file-original] [file-renamed]  # 改名文件,并且将这个改名放入暂存区

修改管理

$ git diff [file]  # 默认是工作区文件和暂存区文件比较;
$ git diff HEAD [file]  # 工作区和HEAD本地库比较

$ git checkout -- file  # 把工作区的修改撤销
$ git reset HEAD file  # 把暂存区的修改撤销掉(unstage)
$ git reset --hard HEAD^  # 把本地库的修改撤销掉(详细请看下面版本回退)

版本回退

git log --pretty=oneline  # 查看(从当前往后的)历史版本,HEAD表示当前版本
git reset --hard HEAD^  # 后退一个版本,一个 ^ 表示一个版本
git reset --hard HEAD~1  # 后退一个版本
git reset --hard commit_id  # 后退或前进到某一个版本
git reflog  # 查看版本变迁

  关于git reset的参数做以下说明:

  • --soft
    • 本地库移动HEAD 指针
  • --mixed
    • 本地库移动HEAD指针
    • 重置暂存区
  • --hard
    • 本地库移动HEAD指针
    • 重置暂存区
    • 重置工作区

 因此,当然一般建议使用--hard

分支管理

  分支管理是git的一大特性,以下分支讲解来自廖学锋的官方网站。在Git里,默认有个分支叫master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

Git详解_第1张图片

  当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

Git详解_第2张图片

  从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
Git详解_第3张图片

  假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

Git详解_第4张图片

  合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
Git详解_第5张图片

$ git branch [-r|a| ] # 列出所有分支, r表示remote、a表示all,当前分支前会标星号
$ git branch [branch-name]  # 新建一个分支,但依然停留在当前分支
$ git branch -d [branch-name]  # 删除分支

$ git checkout -b [branch]  # 新建一个分支,并转到新分支
$ git checkout [branch-name] # 切换分支
$ git checkout -  # 切换到上一个分支

$ git merge [branch]  # 合并指定分支到当前分支,Fast-forward模式
$ git merge --no-ff -m 'merge branch to current branch' [branch]  # 禁用Fast-forward模式【推荐】

$ git checkout -b branch origin/branch  # 创建分支并关联远程分支
$ git branch --set-upstream-to <branch-name> origin/<branch-name>  # 如果创建的时候未关联,可以这样关联

解决冲突

Git详解_第6张图片

  当合并分支遇到上图情况时,就需要手动解决冲突:

Git详解_第7张图片

手动根据实际业务需求修改好之后,再次提交即可:

     git add test.txt

     git commit -m 'fix conflict' test.txt

Git详解_第8张图片

标签管理

  我们经常会看到某某软件对应v1.01,这就是Tag,每个Tag对应于一个commit,不可以移动,且创建的标签默认都只存储在本地,不会自动推送到远程。

# 想在master分支打一个标签

$ git checkout master
$ git tag [-m 'message'] v0.9
$ git log --pretty=oneline --abbrev-commit  # 用这个命令查看历史commit_id
$ git tag v0.9 gt786b7

$ git tag  # 查看当前分支有哪些Tag
$ git show <tagname>  # 查看某个tag信息

$ git tag -d tag_name  # 先删本地标签
$ git push origin :refs/tags/tag_name  # 再删远程标签

$ git push origin <tagname>  # 推送标签
$ git push origin --tags  # 推送所有标签

其他重点

登录方式

  登录方式有两种:账号登录、SSH免密登录,账号登录就不用写了,这里主要说一下SSH登录:

ssh-keygen -t rsa -C "[email protected]"

  会在~/.ssh文件夹下生成id_rsa(私钥,保存好)和id_rsa.pub(公钥)两个文件,然后将公钥中的内容粘贴到下图位置:
Git详解_第9张图片

关联远程库

  关联远程库,主要是关系到工作流程,一种是你新加入一个项目,开始做一个已经有前辈在做的项目,这时候你要先去git服务器上拉取内容;还有一种情况是你做了一项工作一部分,要团队协作了,你将代码上传到git服务器,用git进行版本控制。

  • case1

    mkdir dir_name
    cd dir_name
    git clone url  # 即可拉取git上最新的内容
    
  • case2

    # 先在git服务器上建立一个repository
    git remote add origin project_url  # 建立关联
    git push -u origin master  # 推送到服务器,第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
    

团队协作

  团队协作时的版本控制需要特别注意,因为你并不能更保证你现在的本地库有没有保持最新状态,可以按如下方式push:

  • git push origin branch_name
  • 如果上一步失败,git pull
  • 如果merged有冲突,手动解决,本地提交
  • git push origin branch-name

分叉直线化

  多分支的提交会使历史线有很多的分叉,非常难以观察,这时候可以用到git rebase,关于这一点可以参考rebase

.gitignore

  在.gitignore文件中可以指定忽略的文件或目录,这些文件或目录将不会被提交。当然也可以通过全局配置core.excludesfile来设置过滤规则。推荐大家参考github-gitignore,里面收集了不少常用的配置规则。以下介绍几个相关命令:

  • git add -f [file | dir] 文件被忽略时,强行添加某文件
  • git check-ignore -v file file被莫名忽略,八成.ignore文件写错了,check一下,找到错误

.gitkeep

  Git默认情况下会忽略空的文件夹,如果想要追踪控制空文件夹,根据惯例会在空文件夹下放置.gitkeep文件。Anyway,其实可以放置任何你想放置的文件。

注意事项

  • clone、pull、fetch区别

    1. clone 是本地没有 repository 时,将完整的远程 repository 下载过来
    2. pull 是本地有 repository 时,将远程的repository [某分支或全部]下载过来,并且与本地代码merge,从而保证代码是最新的。
    3. fetch是pull的一个子动作,pull包括fetch和merge两个操作。

Git详解_第10张图片

github-tips

  • 优雅的查看代码历史版本
    假如你正在github上阅读一个文件:https://github.githistory.xyz/jefferyUstc/CaptchaIdentifier/blob/master/predict.py, 这时你想看这个文件的历史代码,你只需要把URL的域名github.com换成:githistory.xyzgithub.githistory.xyzgithub-history.netlify.com 就可以了。
  • 删除github commit历史记录
cd project_name  # 进入项目
git checkout --orphan latest_branch  # 创建"孤儿"分支并进入
git add -A;
git commit -am "first commit";
git branch -D master;  # 删除master分支
git branch -m master; # 将孤儿分支重命名为master分支
git push -f origin master;  # 强制push到远程库

写在篇后

  Git是目前最优秀的版本控制软件,想要熟练它,多做协作项目就好了,总有你意想不到的惊喜等着你!

你可能感兴趣的:(Git)