本文是本人在学习和使用 Git 过程中的一些记录。以备查阅。
随时更新。本文地址:https://segmentfault.com/a/1190000008367711
另外推荐我的另一个 Git 文章:实际操作 Svn 迁移到 Git
Reference
git使用详细介绍
使用 Git 管理源代码
实际操作 Svn 迁移到 Git
git rebase简介(基本篇)
git merge和rebase的区别
git 撤销commit
Git修改已经提交的注释或日志
为 Git 配置扩展命令
git 本地分支和远程分支的跟踪信息的对应
Git push与pull的默认行为
Git基本使用
Permission denied(publickey)错误
为 git 实现 'svn info' 的功能
设置ssh key后push为什么还要输入用户名和密码
Git 基本概念
仓库:也就是 .git
文件。Git 建基于该文件的索引来跟踪改变。每次 commit 都会刷新一次仓库。
Git 忽略机制:可以在与 .git
文件同级的目录下,创建一个 .gitignore
文件,在文件中写上忽略的对象。可以用通配符,也可以用 “#” 注释掉。
项目:一个 repository
对应一个项目;一个 repo 往往又多个仓库。在 GitLab 上面的对应关系是:Group --> Project
.
Git 命令
与 svn 类似的命令
git commit
:在本地更新当前的变更。一般都会加上 -m
或者 -F
参数来附上 message。每次 commit 之后,就会生成其对应的 SHA-1 格式的 commit ID,类似于 svn 里面的 svn version。git help xxx
:查看相应 git 命令的帮助信息git diff .
:查看当前目录的修改内容git add xxx
:将文件 / 目录下的全部内容纳入版本控制git rm xxx
:将文件 / 目录下的全部内容剔除出版本控制并删除git log
:查看当前 repo 的 log 历史。可以带上 -x(x为自然数)指定只显示最近几个 loggit mv xxx
:移动 / 重命名文件 / 目录git status
:与 svn stat
类似,只是输出格式不同。修改的文件会在当前列表前面列出,开头是 “# modified: ...”
Git 特有的新命令
git init
:在当前目录创建一个新的 .git 仓库git merge
:合并指定分支——这是一个庞大的课题,也是 git 的精髓,这里还真没法一时半会说清楚-
git checkout
:切换到本地分支,具体如下:创建一个新的本地分支:
git checkout -b xxx
切换到指定的本地分支:
git checkout xxx
切换到服务器上的某分支:
git checkout xxx
——这个命令会在本地临时创建一个分支查看服务器上的分支列表:
git branch -r
查看分支的基准关系:
git branch -vv
切换到某个 commit ID:
git checkout 相应的commit_id号码
切换到某个 tag:
git checkout xxx
基于某个分支(本地 or 服务器),在本地创建一个新的分支:
git checkout -b 新分支名 基准分支名
还原指定文件至修改之前的状态:
git checkout 文件/目录名
-
git branch
:分支管理。其中部分命令在上面git commit
也有提及。下面也列出主要的功能:查看本地的所有分支:
git branch
查看服务器上的分支列表:
git branch -r
查看分支的基准关系:
git branch -vv
查看当前分支的信息:
cat .git/HEAD
删除本地分支:
git branch -D xxx
比较指定的分支差异:
git diff 分支A 分支B
git tag
:基于某个分支 / commit ID 创建一个 tag:git tag tag名称 基准名称
-
git clone
:从服务器中初始化一个仓库,但需要自行添加 .gitignore 文件。比如:
$ git clone https://github.com/Andrew-M-C/SMB-CIFS_discovery.git .
git pull
:更新服务器代码到本地仓库中,类似于svn up
git push
:将本地修改上传至服务器。这个功能也略微复杂,下文再说git fetch
:类似于 pull,但是不会自动 merge。
Git push
这个命令实际上可以用来控制远程服务器上的分支。比如:
将本地分支的内容推送到服务器的指定分支上:
git push origin 本地分支名:远程分支名
基于本地分支,在远程服务器上新建一个分支:
git push origin 本地分支名:新的远程分支名
删除远程服务器上的分支:
git push origin :远程分支名
,注意 “origin” 和冒号之间有空格
SSH key
Git 可以用 HTTPS 和 SSH 两种方式与 Git 服务器交互。如果仅仅是获取一个只读的 Git 仓库的话(比如从 GitHub 上面拉取别人的开源工程),用 HTTPS 就够了。如果是自己的工程,推荐使用 SSH 方式。
首先,你要配置好你本地的账户名和邮箱名:
git config --global user.name "你的账户"
git config --global user.email "邮箱"
使用 SSH 需要在服务器上上传自己的公钥。生成方法:
ssh-keygen -t rsa -C "你的账户 / 邮箱名"
SSH key 放在 ~/.ssh/id_rsa.pub
文件中
切换账户
本地快速切换账户的时候(同一台机器上操作不同的服务器上的工程),我没有什么方便的方法,也只有使用git config ...
和上一小节提及的 ssh
命令来切换,不过 ssh-keygen
就不用了,改为复制相应的文件就行了。
但如果只是执行上面的几个操作的话,会出现 “Agent admitted failure to sign using the key.
” 的错误。如果是这样的话,那么请执行一次 ssh-add
,然后再去操作就可以了
Git rebase 的用法和与 merge 的区别
Git rebase 是啥
用来把一个远程分支合并到本地分支。简单语法:git rebase 远程分支 本地分支
其中本地分支可以不指定,默认是当前分支。
比如有一个 git 仓库的分支情况为:
A---B---C topic
/
D---E---F---G master
此时如果在 topic 分支上执行 git rebase master
,则分支表会变成:
A'--B'--C' topic
/
D---E---F---G master
换句话说,git rebase 就是:
将当前分支的修改先 patch 下来,然后回退至原版。更新远程分支的修改之后,再应用 patch。
与 git merge 的区别
差别就是 git merge
不会去做 patch 动作。同样以上图为例,在 topic 分支执行了 git merge master
之后,分支情况变成:
A---B---C topic
/ \
D---E---F---G---H master
与 git pull 的区别
实际上,git pull 就是分别调用 merge 和 rebase
使用 merge 模式:
git pull
使用 rebase 模式:
git pull --rebase
Git commit 修改
对于上一个尚未上传到服务器上的 git commit,可以重写 log 或者是直接撤销。
修改 commit log:
git commit --amend
进入界面修改删除指定 commit ID 的修改:
git reset --hard commit_id
撤销指定的 commit 但保留修改:
git reset --soft commit_id
配置自定义的 Git 命令
详细的原理请参考这篇文章。我喜欢在安装了 Git 之后,配置以下命令:
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.st status
$ 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"
重建远程 / 本地分支的对应关系
假设本地分支 BrA
对应着远程分支 origin/dev_A
。当你基于 BrA
拉出一个新的本地分支 BrB
的时候,远程分支对应关系就没了。这个时候就需要重建远程 / 本地分支的对应关系:
git branch --set-upstream BrB origin/dev_A
将 Git 仓库内容清理干净
这个包含两个事情:
删除所有不在版本控制之下的文件
将已修改的文件恢复到版本控制之下的状态
我自己常用的方法并不优雅,但能用。
主要是使用到了rm 命令不会主动删除隐藏文件
这一点(因而就不会去删除.git
文件夹):
$ rm * -rf; git co .
但是比较标准的做法其实是这样的:
$ git clean -fd
$ git co ./
第一句中的 clean,有三个主要参数:
n
:显示出要删除哪些目标,但不删除
——每次清除之前建议执行一次git clean -nfd
确认一下f
:删除不受版本控制的文件d
:删除不受版本控制的目录
GitHub 出现错误提示:“Username for 'https://github.com':”
参见这个问答:
因为你用的是 https 而不是 ssh。
你可以更新一下 origin:
git remote remove origin
git remote add origin git@github.com:Username/Your_Repo_Name.git
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。