每个开发者都应试知道的 Git 命令

前言

读这篇文章之前要求读者要有一些Git的基础,否则,一些细节有可能看不明白。这里我建议大家先读读这本书的前三章。书的链接如下:

https://git-scm.com/book/en/v2

命令速览

git config: To set your user name and email in the main configuration file

git init: To initialise a git repository for a new or existing project

git clone: To copy a git repository from remote source, also sets the remote to original

git status: To check the status of files you’ve changed in your working directory, i.e, what all has changed since your last commit

git add: To adds changes to stage/index in your working directory

git commit: To commits your changes and sets it to new commit object

git push/pull: To Push or Pull your changes to remote. If you have added and committed your changes and you want to push them. Or if your remote has updated and you want those latest changes

git branch: To Lists out all the branches

git checkout: To Switch to different branches

git stash: To Save changes that you don’t want to commit immediately

git merge: To Merge two branches you were working on

git reset: You know when you commit changes that are not complete, this sets your index to the latest commit that you want to work on with

git remote: To check what remote/source you have or add a new remote

Git原理

Git与其它的VCS不同的是,客户端不是只查看文件的最新快照,而是拥有仓库的全部镜像。如果一个Server Down了,任何一个客户端都能把项目完整的还原。Git是分布式版本控制系统,那么它是没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。

配图如下:

Git原理

每次Commit或保存你Git工程的状态时,它会把你那一瞬间的所有文件制成一个快照并引用它。如果文件没有变化,它直接引用到先前存储的快照。

配图如下:

Git原理

Git的配置文件

  1. /etc/gitconfig 包含每个用户以及他们仓库的配置。
  2. ~/.gitconfig 只针对当前用户的配置。
  3. Git目录中的.git/config 针对当前仓库的配置。

以上每一个级别都会覆盖上一个级别的配置。

Git增加文件相关命令

$ git init 创建一个.git目录,以及所有必要仓库骨架。把当前目录变成git可以管理的仓库。

git init

$ git status 显示有变更的文件。
$ git status -s 显示有变更的文件。??表示没有被tracked的文件 A表示没有被加到暂存区(index)的文件 M表示被修改过的文件
$ git add [文件或目录] 把文件添加到暂存区(index)里面去。
$ git commit -m [提交信息] 把暂存区(index)的内容提交到仓库。如果不加-m选项,则会启动你默认的编辑器让你编辑提交信息。
$ git commit [文件1] [文件2] ... -m [提交信息] 提交暂存区的指定文件到仓库。
$ git commit --amend 使用一次新的commit,替代上一次提交。

git commit

$ git diff 显示暂存区和工作区的差异
$ git diff --staged 显示暂存区和上一个commit之间的差异

git diff
上图中:第一个vim我创建了diff.intro的文件,内容是“显示暂存区和工作区的差异”。第二个vim我将文件的内容加了“aaaaa”。
git diff
上图中是显示暂存区和上一个commit之间的差异的一个例子。

$ git log 显示当前分支的版本历史

git log

$ git log -p -2 显示当前分支的版本历史,并显示每个文件的diff信息,并限制输出2个commit

git log

$ git log --oneline 如下图
$ git log --oneline --decorate 如下图

git log

$ git log --oneline --decorate --graph --all 显示commit历史,及分支信息,具体如下图。

git log
git log有很多形式的选项来限制输出信息,具体请查阅文档。

Git撤消文件的修改相关命令

在介绍一些撤消文件的修改命令之前,我先介绍一下2个比较奇怪的符号~和^。它们是指定某个commit的速记法(shorthand),有了它们以后我们就不需要用像cb8bb8c这样的Hash Name来指定某个commit了。具体实例如下:

  • HEAD是HEAD1的简写,它们都表示当前HEAD所指定的commit的第一个双亲。HEAD~2表示当前HEAD所指定的commit的第一个双亲的第一个双亲。以此类推…
  • 一个标准的Merge commit有两个双亲-第一个是merge到当前的commit,第二个是被merge的commit。通常情况下merge实际上有可能有任意多个父亲(octopus merges)。HEAD^(or HEAD1)表示当前HEAD所指定的commit的父母。HEAD2表示当前HEAD所指定的commit的第二个父母。
  • 和~可以混合一起使用。例如:HEAD~32,它表示当前HEAD所指定的commit的第三个双亲的第二个父亲。HEAD^2,它表示当前HEAD所指定的commit的第一个父亲的第二个父亲。HEAD^^和HEAD~3是等价的。

referencing commits from HEAD using ~ and ^

下图为我当前分支状态:

分支状态

现在我要将README.md文件中的内容恢复为“aaaaa”,运行如下命令:

$ git checkout HEAD^2^ 恢复文件到commit b8cd6e3的状态。

分支状态

$ git checkout [文件] 恢复暂存区的指定文件到工作区。
$ git checkout [commit] [文件] 恢复某个commit的指定文件到工作区。
$ git checkout . 恢复上一个commit的所有文件到工作区。
$ git checkout -- [file] 丢弃工作区文件的改变,与上一次commit的文件一致。
$ git reset --hard [commit] 重置暂存区与工作区,与指定的commit保持一致。

git reset

$ git reset --mixed [commit] 它是git reset的默认选项。它重置暂存区,但不重置工作区。

git reset

$ git reset --soft [commit] 它不会重置你的工作区和暂存区

比如说你提交错了一个文件或者commit信息你写错了,那么你可以用这个命令取消上一次的commit,修改正确以后在重新提交。例子如下图:
git reset

从上图我们好看到了重置以后,如果你想的话可以直接提交,因为它并没有重置你的暂存区。上图中我只修改了一下提交信息,你也可以重新修改文件,重新commit。加上-c ORIG_HEAD将打开一个编辑器初始化先前commit的log message,允许你编辑它,如果你想直接使用先前的commit并不想编辑它,用-C代替。

$ git reflog  查看所有分支的所有操作记录,包括commit和reset的操作以及被删除的commit记录
$ git reflog show [分支]  查看某个分支的所有操作记录

Git删除文件相关命令

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

git rm

Git标签相关命令

$ git tag 列出所有tag, 按字母表顺序。
$ git tag -a [标签名] 针对上一次提交创建一个重量级标签。
$ git tag -a [标签名] [commit] 为指定的commit创建一个重量级标签。
$ git tag -d [标签名] 删除指定的标签。
$ git show [标签名] 显示对应这个标签的commit信息。

Git远程同步相关命令

$ git remote -v  显示所有远程仓库。
$ git remote rename [srcremote] [desremote]  修改远程仓库名。
$ git remote show [remote]  显示某个远程仓库的信息。
$ git remote add [shortname] [url]  增加一个新的远程仓库,并命名。
$ git remote rm [remote] 移除远程仓库。
$ git fetch [remote]  下载所有远程仓库的变动到你的本地仓库,但是不merge到你当前的工作空间。并且有了所有远程分支的引用。
$ git push [remote] [branch] 上传本地指定分支到远程仓库。
$ git push [remote] [tag]  提交指定tag到远程仓库。
$ git push [remote] --tags  提交所有tag到远程仓库。

Git分支相关命令

$ git branch  列出所有本地分支。
$ git branch -r  列出所有远程分支。
$ git branch -a  列出所有本地分支和远程分支。
$ git branch -vv  列出所有本地分支及其跟踪的分支。
$ git branch [branch-name]  新建一个分支,但依然停留在当前分支。
$ git branch -d [branch-name]  删除分支
$ git checkout -b [branch-name] 新建一个分支,并切换到该分支。
$ git checkout [branch-name] 切换到指定分支,并更新工作区。
$ git merge [branch]  合并指定分支到当前分支。
$ git branch --track [branch] [remote-branch] 新建一个分支,与指定的远程分支建立追踪关系。
$ git branch --set-upstream-to=[remote-branch]  当前所在的分支与指定的远程分支之间建立追踪关系。
$ git branch [branch] [commit]  新建一个分支,指向指定commit。
$ git branch --set-upstream-to=[remote-branch]  当前所在的分支与指定的远程分支之间建立追踪关系。
$ git push  [remote]  --delete [branch] 删除远程分支。

Git 一些常用的实践场景及解决方案

在这个小节中,我会把我在实际工作中用到的一些场景介绍给大家。针对这些场景我们应该用什么样的git命令解决呢?请大家向下看吧。

保存working directory的变化

假如我有2个分支,一个叫master,另一个叫dev,我当前所在的分支为dev,并对这个分支中的一些文件做了修改。假设,在master分支上现在有些问题需要你马上去解决,但是你当前dev分支的一个功能你并没有完全做完,因此你不能commit,那么问题来了,我们如何回到master去解决问题,然后在回到dev分支继续解决我未完成的问题?下面的这些命令可以解决这个问题。

$ git branch ------ 列出本地的分支,* 表示我当前所在的分支
* dev
master

$ git status ------ 下面的2个文件都做了一些修改,但是还没有完全改完
On branch dev
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   AuthorizationInterceptor.java
	modified:   spring-mvc.xml

$ git stash -p ------ 你可以选择你想stash的文件,每个字母所表示的含义在下面的引用中。

$ git stash list ------ 可以看到所有的stash,如果你有多个stash那么0代表你最新的stash
stash@{0}: WIP on dev: 10183b5 Change logic of task completion

$ git stash show stash@{0} ------ 这里我指定了stash@{0},如果你不指定,Git会默认选择最新的stash
AuthorizationInterceptor.java | 292 +++++++++++++++++++++++++++++------------------------------
spring-mvc.xml                |  11 +--
2 files changed, 148 insertions(+), 155 deletions(-)

$ git checkout master ------ 现在你可以放心地切换回master分支去解决问题吧

$ git checkout dev ------ 解决问题过后,回到dev分支

$ git checkout master ------ 现在你可以放心地切换回master分支去解决问题吧

$ git stash apply stash@{0} ------ 它会把stash@{0}应用到当前的工作目录,如果不指定,默认为stash@{0}

$ git stash pop stash@{0} ------ 和apply基本一样,但是它会把指定的stash从stash列表中移除

通过上面我给出的那些命令,你可以解决我上面给出场景的问题了。

git stash -p 提示时, 每个字母所表示的含义

y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

引用链接: Stash only one file out of multiple files that have changed with Git?

把一个指定的文件还原到指定的commit

假设我把一个文件改的不好,我想回到先前commit的版本,用下面的命令就可以做到了。

$ git log login.jsp ------ 查看login.jsp的commit历史,你也可以加一些选项来过滤

$ git checkout cb0226e login.jsp ------ 把这个文件还原到cb0226e这个commit

取消我本地的commit

假设我更改了一个文件叫做qa,然后把这个文件commit了。过一会我发现qa文件不应该那样去修改,我给改错了。但是,我已经把它commit上去了,那么我应该如何取消错误地那个commit,然后把qa文件正确的修改过后在commit上去呢?下面的命令可以做到:

$ git commit -m "qa文件错误地commit" ----- 这是我错误地commit
$ git reset HEAD~ ------- 把当前HEAD重置到指定的commit
$ vim qa ----------- 现在你来修改qa文件
$ git add qa
$ git commit -c ORIG_HEAD ----- 重用你错误地那个commit对象,并提交

注意:这仅仅是用这个新的commit去替换你那个错误地commit,而不是把你那个错误地commit删除,然后在提交。还有就是git commit 的那个参数c 和 C 是有区别的,用git help commit 自己去看看吧,很简单。

后记

当我们用 ***git fetch [remote]***命令时,我们并没有一个新创建的分支,我们只有一个不能修改的指向远程仓库的引用,例如:origin/master.但是我们可以将其merge到当前工作区,你就有一个可以修改的分支了。

还有最后一个特别方便的命令:

$ git config --global alias.ci commit 设置别名。

以后在提交的时候用***git ci***就可以工作了。

相关链接

http://mislav.net/2010/07/git-tips/

https://dev.to/dhruv/essential-git-commands-every-developer-should-know-2fl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值