Git命令总结

来源:互联网 发布:js面向对象组合继承 编辑:程序博客网 时间:2024/05/16 05:18

git命令总结

使用前配置

为当前用户配置用户名和邮箱:
git config --global user.name "Sam Chow"
git config --global user.email "samchowgo@163.com"

为系统用户配置用户名和邮箱:
sudo git config --system user.name "Sam Chow"
sudo git config --system user.name "samchowgo@163.com"

获取仓库

初始化一个仓库:
git init example这个命令会在当前路径下初始化一个git仓库

克隆一个远程仓库到本地:
git clone git://github.com/samchow/someexample.git

远程仓库

查看当前所有的远程仓库:git remote这个命令至少会显示一个远程仓库,一般是origin
git remote -v在上述命令的基础上,会显示远程仓库的url
git remote show origin查看某个特定的远程仓库信息,此处是origin,同时还会显示pushpull这两个操作关于分支的一些信息。

从远端仓库中获取数据:
git fetch [remote]会从远程仓库拉取本地仓库不存在的数据和分支到本地仓库中,但是并不合并和处理与本地有冲突的分支和数据。

添加一个远程仓库:
git remote add sc [url],这样就创建了一个名叫sc的远程仓库.如果执行git fetch sc,会在本地添加sc的分支,比如sc/master.也可以切换到这个分支上来。

远程仓库的重命名和删除:
git remote rename sc samchow,这条命令会将远程仓库sc改名为samchow.
git remote rm samchow,这条命令会把仓库samchow的远程仓库删除。

分支数据的推送和获取
git pushgit pull命令,远程分支部分总结

git版本库提交相关

查看工作区和暂存区文件差别:git diff

查看工作区和版本库HEAD上文件的的差别:git diff HEAD

查看暂存区和版本库HEAD上文件的差别:git diff --cached或者git diff --staged

查看文件状态:
git statusgit status -s,后者会精简显示。事实上status命令很强大,它会根据上次文件状态和当前文件状态来给出进一步操作的建议,比如如何返回上次文件状态,如何提交等等。
git status -s会用前两列来分别显示相当于git diffgit diff --cached所对应的差距。

将文件从工作区添加到暂存区(此后文件会被追踪):
git add [filename]

注意一点:git diff如果显示有差异,则无法提交

删除文件或移动文件,并保存到暂存区以便提交:
git rm [filename]
git mv [filename]

提交形成新节点:
git commit -m "some comments",注意这里的-m是必须的,后面要跟comment。
注意:要避免使用git commit -a来强制提交

修改最后一次提交(反悔一次)
git commit -amend

查看历史提交

git log该命令会按照时间顺序显示所有提交,并且包含了提交sha-1校验、作者信息、提交时间和提交说明。
git log [-数字],该命令会显示数字个提交。
git log -p,该命令会在原有基础上添加diff信息。
git log --pretty=oneline,该命令会使用一行精简显示历史,只有sha-1和提交说明。另外=后面还可以跟shortfullfullerformat等,其中format可以个性化设置显示。
git log --graph,用ASCII图形显示提交分支的合并历史。
git log --stat,可以显示每次更新的文件修改统计信息。

Git重置——reset

用法1:git reset [--soft | --mixed | --hard] [<commit>]
该用法会改变commit的指向,从而改变提交链。

  • --soft参数:只会更改提交的指向,但是暂存区和工作区的内容不变。
  • --mixed参数:默认情况下会使用该参数,这个参数下,改变提交的指向、清空暂存区差异,但是不改变工作区的内容。
  • --hard参数:该参数下,提交、暂存区、工作区的内容全部更改为修改后的提交所对应的内容。

用法2:git reset [<commit>] [--] [path/filename]
这种用法不会改变提交的引用指向,只会使用某个版本库的文件来覆盖当前暂存区里面的文件.如果不指定commit,则会默认为HEAD。这种情况下,相当于取消git add filename的操作。另外中间的--是可选的。

Git检出——checkout

用法1:git checkout [<commit>] [--] [path/filename]
这种用法是将暂存区和工作区内容变为一致。不同之处在于如果指定了commit,那么会用该commit对应的内容替代当前工作区和暂存区内容;如果不指定的话,那么用当前暂存区覆盖当前工作区。
注意:此处有一个特殊的用法git checkout .或者git checkout -- .,该命令直接用当前暂存区所有文件覆盖工作区所有文件,危险!

用法2:git checkout [<branch>]
该用法如果不指定branch,则对当前HEAD进行检查。
如果指定了branch,那么则将HEAD切换到该分支。

用法3:git checkout [[-b] new_branch] [start_point]
该用法会创建新的分支,如果指定-b,会切换到新的分支上面。start_point代表分支从哪一个特定的提交上面开始创建。另见分支部分的总结。

分支创建和合并

branch

用法1:git branch,显示本地分支列表,并且当前分支会用特殊颜色和星号标记出来。

用法2:git branch <branchname> <strat_point>,创建一个分支,如果指定start_point,那么就从该提交上创建分支。

用法3:git branch -d <branchname>git branch -D <branchname>,删除分支。前者检查分支是否已经合并,如果未合并,那么无法删除。后者则会强制删除。

用法4:git branch -m <branchname>git branch -M <branchname>,重命名分支。前置会检查修改后的名称是否已经存在,后者则会强制重命名。

注意:git checkout -b <newbranch>会创建分支并切换到该分支,而用法2则不会切换到该分支。

分支合并

git merge <branchname>,将branchname合并到当前分支上。
合并之后,会出现一个新的提交。
遇到冲突之后,git会合并失败,此时会停下来,将有冲突的文件标记为unmerged,等待用户自行解决。之后再用git commit系列命令进行手动提交。查找冲突文件时,可以运行git status命令来提示。

分支衍合

git rebase branch1 <branch2>:该命令将branch2或者目前分支的修改作为补丁打到branch1上面(改变了branch2的分支,使之放到branch1后面而不是原有位置)。这样就可以再次git checkout branch1git merge branch2来合并branch1和branch2。
分支衍合适用于打补丁的情况。

注意:一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作。

如果你遵循这条金科玉律,就不会出差错。否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。

不解释为什么,需要借助图示太麻烦。

远程分支

先重新总结一下上面的几个命令

git clone命令,克隆获取远程仓库(假设为origin),并将远程仓库的master作为本地的master,但是origin/master不会随着本地master变化而变化。

git fetch [remote]命令,拉取远程仓库中的分支,但是并不与本地分支对比和合并。假设拉取远程仓库origin,并且origin/master和本地的master出现了分歧,则origin/master和master两个分支同时存在。

推送本地分支push:
git push [remote] [localbranch] [<:remotebranch>]: 向远程仓库推送一个本地分支。注意,这里要推送分支,必须本人有对远程写的权限,而且没有必要把本地所有分支都推送到远程仓库。
推送完自己的本地分支后,其他人再fetch就会获取这个本地分支。

跟踪分支:

  • 这里不是命令,而是一个概念。在从远程仓库获取的分支上面新建本地分支,本地分支就会自动跟踪这个远程仓库的分支。因此git push这个命令没有仓库名和分支名时,会自动找出目前分支对应的远程分支,并推送到远程分支上面。
  • 如果远程仓库存在master分支,那么fetch和clone命令会自动在本地创建一个master分支来跟踪远程分支。
  • git checkout -b <branchname> <remote/branchname>拉取了远程仓库的其他分支之后,可以使用该命令来创建一个新的跟踪分支,并且本地的branchname和远程仓库的branchname不一定同名。
  • 本地分支和远程分支默认是重名的,所有push命令的:remotebranch可以默认不写

获取远程分支且与本地分支合并pull:
git pull,将目前分支跟踪的远程分支拉取并在本地合并,如果不成功则需要用户自己解决冲突。

最后是如何推送本地分支的正确做法:
每次推送之前,先运行git pull命令确认不会和其他成员的推送有冲突(有冲突先解决冲突),再运行git push命令来推送。
切忌使用git push -f来强制推送!

删除远程分支:
git push [remotename] [:remotebranch]:这个写法有点无厘头,用空的本地分支代替远程分支,即将远程分支删除。

暂存

由于分支切换可能比较频繁,导致有些工作尚未达到提交的程度,便需要紧急切换分支。这部分不能提交但是又不能丢失的工作就可以暂存
注意:暂存只是保存了暂存区和工作区的文件,对提交和分支不会造成影响。

git stash:保存当前工作到暂存栈中。
git stash list:列举暂存栈中的内容。
git stash apply <stash@{数字}>:恢复指定的暂存,如果不指定则恢复stash@{0}。该命令不删除栈中的暂存。注意数字是从0开始的。
git stash pop:恢复栈中第一个暂存并将其pop出栈。
git stash drop stash@{数字}:丢弃栈中指定的暂存。

里程碑(打标签)

用于版本的发布使用的标签

查看标签:
git tag:该命令会显示项目中所有的标签。
git tag -l 'v1.2.*':该命令会显示以“v1.2.”打头的标签。
git show v1.2:该命令会显示v1.2的详细信息。

空提交:
git commit --allow-empty -m "empty commit":在新建标签之前,一般需要一个空提交.

新建标签:
用法1: git tag <tagname> [<commit>],创建一个轻量级标签。
用法2: git tag -a -m "msg" <tagname> [<commit>],创建一个带说明的标签。
用法3: git tag -s -m "msg" <tagname> [<commit>],创建一个带GnuPG签名的标签。如果将-s改为-u,则需要选择指定的私钥进行签名。
注意:如果不指定commit,则会将标签打到当前HEAD上面。

推送本地标签:
git push origin v1.2,本地标签不会自动推送,需要手动推送。
git push origin --tags,该命令会将本地所有标签推送。

父提交、祖先提交和分支指针移动表达式

一个^表示一个父提交,如果^后面跟上数字,则表示第几个父提交(用于分支合并时有多个父提交的情况,比如^^2,表示父提交的第二个父提交,因为父提交有分支合并的情况)
~表示祖先提交,后面跟数字表示第n个祖先(~1表示父提交,跟^意思一样)

上述说的是提交历史中的父提交和祖先提交,而<refname>@{n}则表示分支前面第n次改变,比如master@{2}表示master指针两次移动之前所在的提交。这个适合于历史中找不到该提交指针的情况(比如可能是被reset掉了)。

git reflog show <branch> -n:该命令显示某个分支或者HEAD的指针改变情况,显示分支前面的n次改变,注意n是数字。

改变历史

主要是git cherry-pick [commit]git rebase这两个命令。这一部分不涉及交互式命令。

假设有提交A-B-C-D-E-F,master现在指向F,现在我们要去掉提交D。

命令1:git cherry-pick [commit]:该命令将一个提交挑选出来,并且将其以补丁形式“放到”当前HEAD上面,形成一个内容和提交说明都一样的新提交,并将HEAD指向这个提交。

  • 思路1 将HEAD checkout到C上面,使用git cherry-pick master^git cherry-pick master将E-F放到C上面,最后使用git checkout mastergit reset --hard HEAD@{1}将master的指针放到新的F上面。注意:这里的F提交和原来的F提交的sha-1校验值不一样,是不同的提交
  • 思路2 将HEAD checkout到D上面,并且使用git reset --soft HEAD~2,在保存C的暂存区和工作区的情况下,将HEAD指向B,此时提交则会形成一个新的跟D的内容一致的提交。然后利用git cherry-pick命令等做跟思路1相同的操作。

命令2:git rebase --onto <newbase> <since> <till>,先将分支since到till之间的分支(不包括since)作为补丁打到newbase上面,然后将HEAD重新放置到新的till上面,注意这里的till是不同的提交。

  • 思路1: 使用rebase将D HEADrebase到C上面,注意这里是D之后从E开始的分支。然后使用git checkout mastergit reset --hard HEAD@{1}将master指向新生成的F上。
  • 思路2: 使用跟命令1的思路2一样的操作,从B上面提交一个跟D内容一样的提交,然后将E-F rebase到这个提交上面

注意:使用上面这个命令可以丢弃历史提交

反转提交

主要用于远程分支,远程的分支由于多人协同,不能简单地删除提交,正确的作法应该是提交反转。
git revert <commit>,将该commit的父提交再提交一次。

总结rebase命令

上面的分支合并改变历史中都用到了git rebase这个命令,现在总结一下rebase的用法。

git rebase --onto <newbase> <since> <till>,如果缺省till的话,会默认为HEAD。其他的同改变历史 命令2
git rebase <since> <till>,参考分支衍合

交互式衍合:
git rebase -i <since>,运行该命令,会进入一个编辑文件,按照交互式提示来操作。
交互式操作合并提交遇到冲突时:
git reabse --continue,该命令用于衍合遇到冲突而暂停的时候,解决完冲突之后继续衍合。
git reabse --skip,该命令用于衍合遇到冲突而暂停的时候,不解决冲突跳过提交的衍合。
git reabse --abort,该命令用于衍合遇到冲突而暂停的时候,停止衍合回到原来分支的情况。

0 0