一、配置信息
1、配置用户名和邮箱
git config --global user.name "zhangsan"
git config --global user.email zhangsan@163.com
上述命令中的--global
选项,我们要注意一下:
(1)如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。
(2)如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。(极为重要)
2、配置文本编辑器
Git的默认文本编辑器一般是Vi或Vim,如果要使用其他编辑器,可以执行以下命令(以Emacs编辑器为例):
git config --global core.editor emacs
3、差异分析工具
在Git中,还有一个常用的就是解决合并冲突时使用的差异化分析工具,比如vimdiff:
git config --global merge.tool vimdiff
当然,Git也可以理解kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。
4、查看配置信息
git config --list
二、基本命令
在使用Git的过程中,必须掌握基本的命令使用,才能应对各方面的场景需求,以下是常用的命令:
git status /* 显示工作区与暂存区的文件状态 */
git add -u /* 将工作区中的在暂存区有索引的被更改的文件添加到暂存区 */
git add . /* 将所有文件都添加到暂存区*/
git add index.html /* 添加index.html文件到暂存区 */
git commit -m "注释" /* 将暂存区的文件提交到版本库中 */
git pull origin next:master /* 拉取origin主机的next分支,与本地的master分支合并 */
git pull origin next /* 拉取orgin主机的next分支到本地分支 */
git push origin master /* 推送本地分支到origin主机的master分支,如果master分支不存在则自动创建master分支 */
git push origin gh /* 提交gh分支到origin主机上,如果没有则创建gh分支 */
git push origin :master /* 因省略本地分支名称,实际效果相当于删除远程的master分支 */
git push origin --delete master /* 删除远程的master分支 */
git push --all origin /* 将本地所有分支都推送到origin主机,使用前应执行git pull命令进行合并差异 */
git push --force origin /* --force强制推送分支到远程origin主机,慎用 */
git clone git@github.com:indexzero/http-server.git /* 克隆项目 */
git init /* 创建一个新的空仓库 */
git diff index.html /* 比较index.html文件在工作区和暂存区之间的差异 */
git diff --cached index.html /* 比较index.html文件在暂存区和版本库中的差异 */
git diff --cached /* 比较暂存区与版本库差异 */
git diff gh master /* 比较gh分支与master分支之间的差异 */
git diff commit_id1 commit_id2 /* 比较2次提交之间的差异 */
git checkout commit_id /* 检出分支的特定版本 */
git checkout gh /* 切换到名称为gh的分支 */
git checkout index.html /* 检出分支中特定版本下index.html文件到工作区 */
git checkout . /* 检出分支中特定版本下的所有文件到工作区 */
git reset index.html /* 将index.html文件在暂存区中的状态重置为上次提交之后的状态,不影响工作区和版本库*/
git reset --hard HEAD /* 所有文件都彻底重置为上次提交之后的状态,版本库-暂存区-工作区的所有一切都将丢失,慎用 */
git reset --soft HEAD /* 回退版本库中的所有commit提交信息到上次提交后的状态,工作区和暂存区不受影响,如有需要可再次进行commit */
git reset --hard commit_id /* 彻底回退到指定的commit_id的版本, 版本库-暂存区-工作区的一切都将丢失,慎用 */
git revert HEAD /* 反向commit提交上一次的提交 */
git revert commit_id /* 反向commit提交某一次的提交 */
git revert commit_id1..commit_id2 /* 反向commit提交commit_id1和commit_id2之间的所有提交 */
git branch /* 查看本地的所有分支 */
git branch gh /* 创建一个名称为gh的分支 */
git branch -a /* 查看本地和远程的所有分支 */
git merge master /* 合并master分支到本地分支,并自动进行commit */
git log /* 查看所有的commit记录日志 */
git tag /* 查看所有的标签 */
git tag v1.4 /* 创建一个名称为v1.4的轻量级标签 */
git tag -a v1.4 -m '标签v1.4的介绍说明' /* 创建一个名称为v1.4的含附注类型的标签,并添加标签介绍 */
git tag -s v1.4 -m '对名称为v1.4标签的进行签署' /* 签署名称为v1.4的标签 */
git tag -d v1.4 /* 删除名称为v1.4的标签 */
git remote /* 查看已存在的远程分支*/
git remote -v | --verbose /* 查看已存在的远程分支及远程分支的URL */
git remote add origin git@github.com:indexzero/http-server.git /* 添加仓库到远程以供将来引用 */
git rebase /* todo 尚未遇到使用场景,知道该命令但从未使用过,含义比较模糊 */
三、使用场景
1、创建项目Repo
(1)场景1:
场景描述:本地有名称为Demo的仓库,远程主机有一个空的没有任何文件的名称为Demo的仓库,如何进行关联并进行第一次提交。
cd git/demo
git remote add origin git@github.com:zhangsan/demo.git
git push origin master
touch README.md
git add -u
git commit -m "First Commit"
git pull
git push
(2)场景2:
场景描述:只有远程主机有一个空的没有任何文件的名称为Demo的仓库,如何进行进行第一次提交。
cd git
mkdir demo
cd demo
git init
touch README.md
git add -u
git commit -m "First Commit"
git remote add origin git@github.com:zhangsan/demo.git
git push origin master
(3)场景3:
场景描述:在远程主机上,有一个只有README.md文件,没有本地项目,如何进行第一次提交。
cd git
git clone git@github.com:zhangsan/demo.git
touch index.html
git add -u
git commiit -m "First Commit"
git pull
git push
2、代码回滚
(1)场景4:
场景描述:在项目暂停阶段,当我们正在master分支中调试一个任务A,然而突然有一天,项目有一个紧急的任务需要立即开始,然而任务A并未完成,虽然不是项目的一部分,但是却异常重要。这个时候,我们要保证的就是既要保留下这一任务A代码,又不得将其提交到项目中?
面对这一种情形,我们可以这样来应对:
解决方案:将任务A相关的代码放置在另一个名称为a_test_branch的新分支中,不提交a_test_branch分支到远程服务器。这样我们下次就可以在原先的基础之上继续调试任务A。平行世界来回穿梭,非常完美。。
git branch a_test_branch
git checkout master
(2)场景5:
场景描述:在完成任务后,准备提交代码之前,突然想起来README.md文件最后添加有一行“My stupid boss still prefers SVN”,而这个可能会让你得罪Boss,既然错误发现的很及时,当然可以很容易的纠正。
面对这一情形,这里分为3种应对方法:
① 如果还没有提交到暂存区,手动删除掉最后一行,继续完成提交。这种方法在面对错误量极少的情况下可行,如果文件中错误杂乱,无法手动恢复,则该应对方案将完全失效。
② 如果还没有提交到暂存区,在我们执行git status
命令对比文件差异时,我们发现可以执行git checkout README.md
命令丢弃README.md文件在工作区的修改,使其恢复到上一次提交后的状态。
③ 如果此时已将其添加到暂存区,我们可以使用git reset HEAD README.md
使其恢复到上次提交以后的状态。
(3)场景6:
场景描述:当你完成一个任务后,突然发现将一个非常关键的带有你的账户用户名密码的文件给提交了,可能造成信息泄露,总之可能很惨。
面对这一情形,有多种情况需要应对:
① 已将该文件添加到暂存区,但还没有进行commit提交,这个时候我们可以使用git rm user.md
命令将该文件从暂存区和工作区彻底删除。
② 已将该文件commit提交到了版本库,但还没有push到远程,这时候你应该庆幸还可以再抢救一下。这个时候我们可以使用git reset --soft HEAD
命令在不影响暂存区和工作区的安全环境下撤销提交,然后执行git rm user.md
从暂存区和工作区彻底删除该机密文件,然后重新进行commit提交。
③ 如果此时已将该机密文件push到远程主机,那可真惨了。但也不是不可挽救,这一种情况在场景7中进行详细描述。
(4)场景7:
场景描述:当你完成一个任务后,突然发现将一个非常关键的带有你的账户用户名密码的文件给提交了,而且还给push到了远程主机,Boss要求立马无痕的进行代码回滚。
问题解决要求:这种场景是有点儿复杂,而且危险系数非常高,一不留神可能造成更严重的后果。这里的要求非常明确,就是有关机密文件的提交必须在提交Log中无痕的消失,同时正确的commit提交的Log也必须尽可能的保留。
问题场景的情形:这种场景下有2种情形:
① 错误的commit提交之后,再没有其他的任何提交
② 错误的commit提交之后已有非常多的其他人的提交
问题解决思路:
① 对于场景的情形1,我们可以使用git reset --soft HEAD
命令在不影响暂存区和工作区的前提下,回滚代码到错误提交之前的那一个版本,然后重新进行最后一次提交,然后使用git push --force
命令强行推送并覆盖错误的版本,这样就实现了无损回滚。可以这样说“回到过去并改变了未来走向”;
② 对于场景的情形2,这一种情况着实复杂。可以做出这样一个比喻:“回到过去某一个时间节点并改变该时间节点所发生的错误的事情,要求不能改变该节点之前的历史记录,亦不能改变该节点之后的未来的事件走向”。我们可以从平行空间的角度来思考问题:
Git是一个无所不能的工具,可以随时随地依照某一个分支(空间)的某一个历史版本(时间节点)创造一个新的分支(平行空间),同时也可以将分支(空间)的一些正确的历史版本(时间节点)原模原样的移植到另一个分支(平行空间),依照这样的能力,我们可以做这样的设想:
首先我们需要使用Git创造一个以现分支master分支为基础的新分支gh分支,然后我们切换到gh分支,在gh分支将代码回滚到错误提交之前的那个历史节点,并重新commit那一次错误的提交,然后再回到master分支,并将错误提交之后的所有提交都原模原样的搬迁到gh分支,并解决冲突,待确保完全没有问题之后使用gh分支彻底代替master分支,这样应该就可以解决了问题。大概的命令如下(只是一个初步思路,并未经过实际验证,请谨慎使用,有不怕死的可以蹚一蹚,看看水有多深):
git branch gh /* 创建gh分支 */
git checkout gh /* 切换到gh分支 */
git reset --hard commit_id5 /* 回滚代码到错误提交之前的版本节点,并修改补充那次错误的提交 */
git add -u
git commit -m "错误提交:修改"
git push --force origin gh
git rebase master
(5)场景8:
场景描述:当我们完成了代码提交后(还没有push),突然发现commit提交信息马马虎虎,竟让人看不明白,这时候我们完全重新进行这一次提交。
解决思路:使用git commit -amend
重新提交。