美文网首页Git笔记linux操作系统
Git 笔记系列(三)—— Git常用命令

Git 笔记系列(三)—— Git常用命令

作者: 吃蘑菇De大灰狼 | 来源:发表于2018-04-14 15:22 被阅读7次
    时间 更新备注
    2018-02-28 新建文章
    2018-06-08 整理补充

    目录

    Git 命令图解

    image

    命令

    image
    • workspace: 本地的工作目录。(记作A)
    • index:缓存区域,临时保存本地改动。(记作B)
    • local repository: 本地仓库,只想最后一次提交HEAD。(记作C)
    • remote repository:远程仓库。(记作D)
      以下所有的命令的功能说明,都采用上述的标记的A、B、C、D的方式来阐述。

    初始化

    git init //创建
    git clone /path/to/repository //检出
    git config --global user.email "you@example.com" //配置email
    git config --global user.name "Name" //配置用户名
    

    操作

    git add <file> // 文件添加,A → B
    git add . // 所有文件添加,A → B
    git commit -m "代码提交信息" //文件提交,B → C
    git commit --amend //与上次commit合并, *B → C
    git push origin master //推送至master分支, C → D
    git pull //更新本地仓库至最新改动, D → A
    git fetch //抓取远程仓库更新, D → C
    git log //查看提交记录
    git status //查看修改状态
    git diff //查看详细修改内容
    git show //显示某次提交的内容
    
    撤销操作
    git reset <file>//某个文件索引会回滚到最后一次提交, C → B
    git reset//索引会回滚到最后一次提交, C → B
    git reset --hard // 索引会回滚到最后一次提交, C → B → A
    git checkout // 从index复制到workspace, B → A
    git checkout -- files // 文件从index复制到workspace,用来丢弃本地修改, B → A 
    git checkout HEAD -- files // 文件从local repository复制到workspace, C → A
    

    分支

    git checkout -b branch_name //创建名叫“branch_name”的分支,并切换过去
    git checkout master //切换回主分支
    git branch -d branch_name // 删除名叫“branch_name”的分支
    git push origin branch_name //推送分支到远端仓库
    git merge branch_name // 合并分支branch_name到当前分支(如master)
    git rebase //衍合,线性化的自动, D → A
    
    冲突处理
    git diff //对比workspace与index
    git diff HEAD //对于workspace与最后一次commit
    git diff <source_branch> <target_branch> //对比差异
    git add <filename> //修改完冲突,需要add以标记合并成功
    

    git reset

    详细见Git 笔记系列(五)—— Git常用命令-Reset

    image

    重置命令(git reset)是Git最常用的命令之一,也是最危险,最容易误用的命令。来看看git reset命令的用法。

    用法一:git reset [-q] [<commit>] [--] <paths>...

    用法二:git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]

    上面列出了两个用法,其中<commit>都是可选项,可以使用引用或者提交ID,如果省略 <commit>则相当于使用了HEAD的指向作为提交ID
    上面列出的两种用法的区别在于,第一种用法在命令中包含路径<paths>。为了避免路径和引用(或者提交ID)同名而冲突,可以在<paths>前用两个连续的短线(减号)作为分隔。

    第一种用法(包含了路径<paths>的用法)不会重置引用,更不会改变工作区,而是用指定提交状态(<commit>)下的文件(<paths>)替换掉暂存区中的文件。例如命令git reset HEAD <paths>相当于取消之前执行的git add <paths>命令时改变的暂存区。

    第二种用法(不使用路径<paths>的用法)则会重置引用。根据不同的选项,可以对暂存区或者工作区进行重置。参照下面的版本库模型图,来看一看不同的参数对第二种重置语法的影响。

    git reflog

    如果没有记下重置前master分支指向的提交ID,想要重置回原来的提交真的是一件麻烦的事情(去对象库中一个一个地找)。幸好Git提供了一个挽救机制,通过.git/logs目录下日志文件记录了分支的变更。默认非裸版本库(带有工作区)都提供分支日志功能,这是因为带有工作区的版本库都有如下设置:

    $ git config core.logallrefupdates
    true
    

    查看一下master分支的日志文件.git/logs/refs/heads/master中的内容。下面命令显示了该文件的最后几行。为了排版的需要,还将输出中的40位的SHA1提交ID缩短形式。

    $ tail -5 .git/logs/refs/heads/master
    dca47ab a0c641e Jiang Xin <jiangxin@ossxp.com> 1290999606 +0800    commit (amend): who does commit?
    a0c641e e695606 Jiang Xin <jiangxin@ossxp.com> 1291022581 +0800    commit: which version checked in?
    e695606 4902dc3 Jiang Xin <jiangxin@ossxp.com> 1291435985 +0800    commit: does master follow this new commit?
    4902dc3 e695606 Jiang Xin <jiangxin@ossxp.com> 1291436302 +0800    HEAD^: updating HEAD
    e695606 9e8a761 Jiang Xin <jiangxin@ossxp.com> 1291436382 +0800    9e8a761: updating HEAD
    

    可以看出这个文件记录了master分支指向的变迁,最新的改变追加到文件的末尾因此最后出现。最后一行可以看出因为执行了git reset –hard命令,指向的提交IDe695606改变为9e8a761
    Git提供了一个git reflog命令,对这个文件进行操作。使用show子命令可以显示此文件的内容。

    $ git reflog show master | head -5
    9e8a761 master@{0}: 9e8a761: updating HEAD
    e695606 master@{1}: HEAD^: updating HEAD
    4902dc3 master@{2}: commit: does master follow this new commit?
    e695606 master@{3}: commit: which version checked in?
    a0c641e master@{4}: commit (amend): who does commit?
    

    使用git reflog的输出和直接查看日志文件最大的不同在于显示顺序的不同,即最新改变放在了最前面显示,而且只显示每次改变的最终的SHA1哈希值。还有个重要的区别在于使用git reflog的输出中还提供一个方便易记的表达式:<refname>@{<n>}。这个表达式的含义是引用<refname>之前第<n>次改变时的SHA1哈希值。
    那么将引用master切换到两次变更之前的值,可以使用下面的命令。
    重置master为两次改变之前的值。

    $ git reset --hard master@{2}
    

    HEAD is now at 4902dc3 does master follow this new commit?

    重置后工作区中文件new-commit.txt又回来了。

    $ ls 
    new-commit.txt  welcome.txt
    

    提交历史也回来了。

    $ git log --oneline
    4902dc3 does master follow this new commit?
    e695606 which version checked in?
    a0c641e who does commit?
    9e8a761 initialized.
    

    此时如果再用git reflog查看,会看到恢复master的操作也记录在日志中了。

    $ git reflog show master | head -5
    4902dc3 master@{0}: master@{2}: updating HEAD
    9e8a761 master@{1}: 9e8a761: updating HEAD
    e695606 master@{2}: HEAD^: updating HEAD
    4902dc3 master@{3}: commit: does master follow this new commit?
    e695606 master@{4}: commit: which version checked in?
    

    git remote

    1. 添加远程库: $ git remote add origin
    2. 移除远程库: $ git remote remove (OrignName)
    3. 查看远程库: $ git remote -v(--verbose)

    git grep查找

    git grep -n "要查找的字符串"

    1. -W 查找函数上下文
    2. 使用 --count 参数, 只会显示在哪个文件里有几个要查找的字符串, 如下:
      git grep --count "(defun format "

    src/format.lisp:1

    可以使用 $ git help grep 来查看帮助

    Git 其他常用命令

    Git undo撤销方法

    1. git revert <SHA>
    2. git commit --amend -m "Modify last add message"
    3. 撤销本地的修改git checkout -- <bad filename>
    4. 重置本地的修改git reset <last good SHA>

    Git的各种Undo技巧

    Git Merge

    使用XcodeFileMerge合并代码

    # Tell system when Xcode utilities live:
    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
    
    # Set "opendiff" as the default mergetool globally:
    git config --global merge.tool opendiff
    
    1. 代码冲突! [rejected] master -> master (non-fast-forward)的原因以及解决办法:
     ! [rejected]        master ->  master (non-fast-forward)  
    error: failed to push some refs to 'git@github.com:archermind/LEDTorch.apk-for-Android.git'  
    To prevent you from losing history, non-fast-forward updates were rejected  
    Merge the remote changes before pushing again.  See the 'Note about  
    fast-forwards' section of 'git push --help' for details.  
    

    操作命令:

    • 正确的做法是,在push之前git fetch origin,将github上的新代码拉下来,然后在本地merge,如果没有冲突就可以push了,如果有冲突的话要在本地解决冲突后,再push。具体做法就是:
    git fetch origin
    git merge origin (master)
    
    • 这两步其实可以简化为
    git pull origin master
    

    git-fetch - Download objects and refs from another repository
    git-merge - Join two or more development histories together

    Git log

    Table 3. 限制 git log 输出的选项
    选项  说明
    -(n)
    
    仅显示最近的 n 条提交
    
    --since, --after
    
    仅显示指定时间之后的提交。
    
    --until, --before
    
    仅显示指定时间之前的提交。
    
    --author
    
    仅显示指定作者相关的提交。
    
    --committer
    
    仅显示指定提交者相关的提交。
    
    --grep
    
    仅显示含指定关键字的提交
    
    -S
    
    仅显示添加或移除了某个关键字的提交
    
    来看一个实际的例子,如果要查看 Git 仓库中,2008 年 10 月期间,Junio Hamano 提交的但未合并的测试文件,可以用下面的查询命令:
    
    $ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
       --before="2008-11-01" --no-merges -- t/
    5610e3b - Fix testcase failure when extended attributes are in use
    acd3b9e - Enhance hold_lock_file_for_{update,append}() API
    f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
    d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
    51a94af - Fix "checkout --track -b newbranch" on detached HEAD
    b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch
    在近 40000 条提交中,上面的输出仅列出了符合条件的 6 条记录。
    
    1. 显示每次提交的diff:
    git log -p 
    
    1. 按成员的提交历史
    git shortlog
    
    1. 在提交的历史改动中查找关键字,-p代表显示log提交的改动
    git log -S"searchKeyWord" -p
    

    5, 搜索提交的注释

    git log --grep=“keyWord” 
    
    1. 搜索某个用户的提交
    git log --author=“authorName” 
    

    Git diff

    通过使用不同的参数调用git diff命令,可以对工作区、暂存区、HEAD中的内容两两比较。下面的这个图,展示了不同的git diff命令的作用范围。

    image image
    diff: 分支点之间的变化
    分支点的继承
    当add了change后, git diff是不会显示已经add后的change的,可以制定stage的diff
    git diff --staged
    

    Git config

    Git的配置

    1. 列出Git全局配置列表
    git config --global --list
    
    1. 列出Git本地仓库配置列表
    git config --local --list
    
    1. 设置用户名,邮箱密码等
    $ git config --global user.name "John Doe"
    $ git config --global user.email johndoe@example.com
    
    1. 设置编辑器
    $ git config --global core.editor emacs
    

    设置git命令 别名

    $ git config --global alias.st status
    $ git config --global alias.co checkout
    $ git config --global alias.ct commit
    $ git config --global alias.df diff
    $ git config --global alias.br branch
    #git lg to view commit log like network graph
    $ git config --global alias.lg "log --all --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%ci) %C(bold blue)<%an>%Creset' --abbrev-commit"
    
    Git命令的别名

    有些Git的命令很长,如果经常输入就很繁琐,通过设置Git的别名,可以简化输入,提交效率,这里推荐一个Git的别名库,方便使用各种Git命令。

    git-extras/Commands.md at master · tj/git-extrasGIT utilities -- repo summary, repl, changelog population, author commit percentages and more

    同一台电脑可以有2个git账号(不同网站的)

    1.同一台电脑可以有2个git账号(不同网站的)

    这种情况下,需要几点注意

    1.remote pull push的时候有问题,因为要设置邮箱问题了 pull的时候识别的是邮箱,2个github账号,2个邮箱,我们自然不能使用global的user.email了

    1.取消global

    git config --global --unset user.name
    git config --global --unset user.email
    

    2.设置每个项目repo的自己的user.email

    git config  user.email "xxxx@xx.com"
    git config  user.name "suzie"
    

    之后push pull就木有问题了

    备注
    生成ssh key

    ssh-keygen -m rsa -C "your mail (当前目录) 然后可以命名默认id_rsa或者id_rsa_second 把对应的pub放到公共服务器上。

    其他

    gitk //开灯图形化git
    git config color.ui true //彩色的 git 输出
    git config format.pretty oneline //显示历史记录时,每个提交的信息只显示一行
    git add -i //交互式添加文件到暂存区
    

    常见命令菜单

    Git Cheat Sheet Part1

    看了前面那么多命令,是不是有点多了?ㄟ( ▔, ▔ )ㄏ平时开发用的到那么多命令吗?Don`t worry,常用的命令只需看下面几张图即可:

    Git Cheat Sheet

    Git Cheet Sheet Part2

    image
    image

    参考

    1. git reset soft,hard,mixed之区别深解
    2. Git - git-reset Documentation

    相关文章

      网友评论

        本文标题:Git 笔记系列(三)—— Git常用命令

        本文链接:https://www.haomeiwen.com/subject/nuslkftx.html