Git:基本操作

来自Wikioe
跳到导航 跳到搜索


常用操作

Git基本操作.jpg

仓库

命令 说明 备注
git init 初始化Git仓库
  1. git init:在当前目录初始化Git仓库
  2. git init <newrepo>:在指定目录(<newrepo>)初始化Git仓库
git clone 克隆Git仓库
  1. git clone <repo>:克隆仓库(<repo>)到当前目录
  2. git clone -o<远程主机名> <repo>:克隆仓库(<repo>)当前目录,并为远程主机设置主机名
  3. git clone <repo> <directory>:克隆仓库(<repo>)到指定目录(<directory>

修改

命令 说明 备注
git add 将工作区新增或修改的文件添加到暂存区
  1. git add [file1] [file2]:添加一个或多个文件到暂存区;
  2. git add [dir]:添加指定目录到暂存区(包括子目录);
  3. git add .:添加当前目录下的所有文件到暂存区;
  4. git add -f [file]:强制添加存在于.gitignore的文件;
git commit 提交暂存区到本地仓库
  1. git commit -m [message]:提交暂存区到本地仓库;
  2. git commit [file1] [file2] -m [message]:提交暂存区的指定文件;
  3. git commit ([file1] [file2]) -am [message]:直接提交(跳过git add);
git status 查看仓库当前的状态,显示有变更的文件
Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation保留所有权利

D:\git\eijux>git status
On branch master
Your branch is up to date with 'eijux/master'.

Changed not staged for commit:
  (use "git add <file>..." to include in what will be committed)
  (use "git restore --staged <file>..." to unstage)
        new file:   1.txt

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   2.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        3.txt
  1. Changed not staged for commit:修改文件,未add
  2. Changes to be committed:修改并add,未commit
  3. Untracked files:新增文件,从未add
git diff 比较文件的不同,即暂存区和工作区的差异
  1. git diff ([file]):查看暂存区和工作区的改动;
  2. git diff --cached ([file]):(或git diff --staged ([file]))暂存区和上一个commit的差异;
  3. git diff HEAD ([file]):查看工作区与当前分支最新commit之间的差异;
  4. git diff [branchName] [file]:当前分支的文件与[branchName]分支的文件进行比较;
  5. git diff [commitId] [file]:当前分支的文件与[commitId]提交的文件进行比较;
  6. git diff --stat:显示摘要而非整个diff;
  7. git diff [first-branch]...[second-branch]:查看两次提交之间的差异;
git stash 保存工作现场
  1. git stash list:查看所有保存的工作现场;
  2. git stash apply <stash>:恢复stash(但不删除);
  3. git stash drop <stash>:删除stash;
  4. git stash pop <stash>:恢复并删除stash;
  5. <stash>形如“stash@{0}”,可在list中看到:
    • e.g. git stash pop stash@{0}
git reset 回退版本

git reset [--soft | --mixed | --hard] [HEAD]
关于参数:

  1. --soft:将HEAD指向指定commit(这使得所有更改的文件都“等待提交”);
  2. --mixed:(默认)重置索引,但不重置工作树(保留更改的文件,标记为:未提交?未add?);
  3. --hard:重置索引和工作树(自<commit>以来对工作树中跟踪文件的任何更改都将被丢弃);
  4. --merge:重置索引,并
    1. 在工作树中更新‘<commit>与HEAD不同’的文件,
    2. 在工作树中保留‘索引与工作树不同’的文件(即,未add的更改)。
    3. 如果‘<commit>和索引不同’的文件具有未暂存的更改,则会中止重置。
  5. --keep:重置索引,并
    1. 在工作树中更新‘<commit>与HEAD不同’的文件。
    2. 如果‘<commit>与HEAD不同’的文件具有本地修改,则会中止重置。
参考Documentation:Reset的DISCUSSION一节

关于[HEAD]:

  1. 当前版本:HEADHEAD~0
  2. 上一个版本:HEAD^HEAD~1
  3. 上上一个版本:HEAD^^HEAD^2
  4. 上上上一个版本:HEAD^^^HEAD^3
    以此类推

版本回退:

  1. git reset --hard HEAD^:回退到上一次commit;
  2. git reset --hard <commitID>:回退到指定commit之前;
git revert 撤销操作
  1. revert是将需要的版本内容反向修改回去,并提交一个新版本;
  2. git revert HEAD:撤销前一次 commit;
  3. git revert HEAD^:撤销前前一次 commit;
  4. git revert <commitID>:撤销指定的版本;
git restore

文件恢复
Git 2.23引入

Note1: git restore [<options>] [--source=<tree>] [--staged] [--worktree] [--] <pathspec>

  1. [--source=<tree>]:指定还原源:
    1. 默认(不设置)从索引恢复内容;
    2. 若指定--staged,则从HEAD恢复内容;
  2. [--staged] [--worktree]:指定恢复目标:
    1. 默认(不设置)恢复到工作树的内容;
    2. --staged:用于恢复索引的内容;
    3. --staged --worktree:用于同时恢复索引和工作区的内容;
  • 注意:使用“还原源”中的某些内容还原“工作树指定路径”:如果“工作树被跟踪路径”不存在与还原源中,则将删除该路径以匹配源;

Note2:

  1. git restore --staged <file>:从HEAD恢复<file>到索引,
    等效于git reset <file>
  2. git restore --source=HEAD --staged --worktree <file>:从HEAD恢复<file>到索引和工作树,
    等效于git checkout -- <file>
git mv 移动或重命名工作区文件
  1. git mv -f [file] [newfile]:强制执行;
git rm 删除工作区文件
  1. git rm <file>:将文件从暂存区和工作区中删除;
  2. git rm --cached <file>:将文件从暂存删除,工作区保留(即停止追踪指定文件,通常是在文件曾经被git管理过,现在不需要被git接管的时候使用);
  3. git rm -r *:递归删除;
  4. git rm -f <file>:强制删除;

关于撤销工作区修改

  1. 若工作区修改未add到stage:
    git checkout -- <file>
  2. 若工作区修改已add,但未commit:
    1. git reset HEAD <file>(1、从版本库commit中恢复到stage)
    2. git checkout -- <file>(2、撤销工作区修改)

分支

命令 说明 备注
git branch 分支命令
  1. git branch:查看所有本地分支
  2. git branch -r:查看所有远程分支
  3. git branch -a:查看本地和远程的所有分支
  4. git branch <branchname>:创建<branchname>分支
  5. git branch -d <branchname>:删除<branchname>分支
  6. git branch -D <branchname>:强制删除一个未被合并过的分支<branchname>
  7. git branch --set-upstream <本地分支名> <远程主机名>/<远程分支名>:手动在本地分支与远程分支间建立追踪关系;
git checkout 签出分支(或文件)

分支:

  1. git checkout <branchname>:切换到<branchname>分支
  2. git checkout -b <branchname>创建并切换到<branchname>分支
  3. git checkout -b <本地新建分支> <远程主机名>/<远程分支>:在远程分支基础上新建本地分支(先有远程主机信息git fetch <远程主机名> <远程分支>
切换分支的时候,Git会用该分支最后提交的快照替换本地工作目录的内容。

文件: git checkout [<options>] [<branch>] -- <file>

  1. git checkout -- <file>:从当前分支签出文件(即撤销工作区文件<file>的修改);
    1. 工作区修改,但未add到暂存区:checkout重置到与版本库一致
    2. 工作区修改并add后,再次修改:checkout重置到与暂存区一致
  2. git checkout <commit> -- <file>:从指定commit签出文件;
  3. git checkout <branch> -- <file>:从指定分支签出文件;
  4. git checkout -- *.xxx:签出所有xxx后缀的文件;
  5. git checkout -- xxx/:签出所有xxx目录的文件;
git merge 分支合并

Note1: Git merge.png

  1. 合并分支并产生新的提交
  2. 不会改变当前分支的开始位置;
  3. 只处理一次冲突;
  4. 引入了一次合并的历史记录,合并后的所有 commit 会按照提交时间从旧到新排列;
  5. 合并后分支过程信息更多更复杂,可能会提高之后查找问题的难度;

Note2:参数

  • (N = 被合并分支中,需要合并的commit个数)
  • (主分支和被合并分支中,被合并的commitID并不相同,是重新提交,而非引用)
  1. --ff:(默认)快速合并(主分支新增N个commit,冲突处理则N+1);
    如果合并过程出现冲突,Git会显示出冲突并等待手动解决;
  2. --ff-only:只有能快速合并的情况才合并(主分支新增N个commit);
    如果合并过程出现冲突,Git会自动abort此次merge;
  3. --no-ff:不使用快速合并(主分支新增N+1个commit,冲突处理则N+2);
    会额外生成一次新的提交记录,用于标识此处进行了一次merge操作(需使用-m <message>记录提交信息);
  4. --squash:压缩合并(主分支新增1个commit);
    将待合并的分支的内容压缩成一个新的提交合并进来;

Note3:

  1. git merge <branch1>:将<branch1>分支合并到当前分支;
    branchB和并到branchA:切换到branchA中执行“git merge branchB”。
  2. git merge <branch1> <branch2> <branch3> <branch4>:合并多个分支到当前分支;
git rebase 分支(变基)合并

Note1: Git rebase.png

  1. (变基)合并分支但并不产生新的提交
  2. 改变了当前分支的开始位置
  3. 可能会有多次冲突处理
  4. 没有多余的合并历史的记录,且合并后的 commit 顺序不一定按照 commit 的提交时间排列
  5. 合并后分支上每个 commit 点都是相对独立完整的功能单元;

Note2:

  1. git rebase <branch1>
  2. git rebase --continue:(解决完冲突并git add后)继续应用(apply)余下的补丁进行合并;
  3. git rebase --abort:终止rebase的行动,并将分支回退到rebase开始前的状态;
git cherry-pick

复制commit

Note1:

  1. git cherry-pick <commit>:是将指定的提交(commit)应用于当前分支,这会在当前分支产生一个新的提交;
  2. git cherry-pick <branch>:表示应用该分支的最新提交,到当前分支;

Note2:

  • 复制多个commit时,当前分支会产生多个对应的commit。
  1. git cherry-pick <commitA> <commitB> <commitC>:复制多个commit;
  2. git cherry-pick <commitA>...<commitC>:(不包括<commitA>)复制从<commitA><commitC>的多个commit(<commitA>必须在<commitC>之前);
  3.  git cherry-pick <commitA>^...<commitC>:(包括<commitA>)复制从<commitA><commitC>的多个commit(同上);
  • cherry-pick 也支持转移另一个代码库的提交,方法是先将该库加为远程仓库,再抓取代码并获取<commitID>

Note3:

  1. git cherry-pick --continue:用于解决代码冲突后,让cherry-pick过程继续执行(先将修改的文件加入暂存区git add);
  2. git cherry-pick --abort:发生代码冲突后,放弃cherry-pick过程,恢复到操作前状态;
  3. git cherry-pick --quit:发生代码冲突后,放弃cherry-pick过程,但不恢复状态;
git switch

切换分支
Git 2.23引入

git checkout分支等效:

  1. git switch <branch>分支:等效于git checkout <branch>
  2. git switch -c <branch>分支:(--create)等效于git checkout -b <branch>分支

冲突合并:
冲突合并涉及文件添加、移除的操作,还包括文件修改内容的合并。

远程

命令 说明 备注
git remote 管理远程仓库主机名
  1. git remote -v:显示所有远程仓库
  2. git remote show [remoteName]:显示远程仓库的信息
    如:git remote show origin
  3. git remote add [remoteName] [url]:添加关联远程版本库
    如:git remote add origin git@github.com:tianqixin/runoob-git-test.git
  4. git remote rm [remoteName]:删除远程仓库
  5. git remote rename [old_name] [new_name]:修改远程仓库名
git pull

下载远程代码并合并:
git pull <远程主机名> <远程分支名>:<本地分支名>

Note1:

  1. 合并到当前分支,可省略“:<本地分支名>”;
  2. 等效于git fetch+git merge FETCH_HEAD(概念上等效,实现上不一样???)。

Note2:

  1. git pull --rebase <远程主机名> <远程分支名>:<本地分支名>:合并需要采用rebase模式的pull;
  2. git pull -p:若服务器删除了某分支,拉取远程分支的时候,同步删除本地的该分支;
    等同于:git fetch --prune <远程主机名>git fetch -p

Note3:

  1. git pull <远程主机名> <远程分支名>
    拉取远程主机的分支,并与本地当前分支合并;
  2. git pull <远程主机名>
    拉取远程主机的对应分支,并与本地当前分支合并(当前分支与远程分支必须存在追踪关系);
  3. git pull
    拉取远程主机的对应分支,并与本地当前分支合并(当前分支只有一个追踪分支);
git push

上传远程代码并合并:
git push <远程主机名> <本地分支名>:<远程分支名>

Note1:

  1. git push --delete:删除远程主机的分支;
  2. git push --force:(慎用)强制推送,忽略远程分支版本比本地高(应先pull);
  3. git push --all:无论对应远程分支是否存在,将本地的所有分支都推送到远程主机;
  4. git push --tags:推送所有未推送过的本地标签;
  5. git push <tag>:推送本地标签<tag>;

Note2:

  1. git push -u <远程主机名> <本地分支名>
    如果当前分支与多个主机存在追踪关系,则可以使用-u参数指定一个默认主机,这样后面就可以不加任何参数使用git push;
  2. git push <远程主机名> <本地分支名>
    表示将本地分支推送到与之存在追踪关系的远程分支(通常两者同名),如果该远程分支不存在,则会被新建;
  3. git push <远程主机名> :<远程分支名>
    表示删除对应的远程分支(推送空的本地分支到远程);
  4. git push <远程主机名>
    表示将当前分支推送到远程主机的对应分支(当前分支与远程分支必须存在追踪关系);
  5. git push
    表示将当前分支推送到远程主机的对应分支(当前分支只有一个追踪分支);

Note3:关于推送方式

  1. simple方式:不带任何参数的git push,默认只推送当前分支;(默认)
  2. matching方式:推送所有有对应的远程分支的本地分支;(Git 2.0之前默认)
  3. git config中的push.default可配置推送方式;

git fetch

获取远程主机的版本库更新(commit):git fetch [alias] [branch]

Download objects and refs from another repository

Note1:

  1. FETCH_HEAD:是一个版本链接,记录在本地的文件中(.git/FETCH_HEAD),指向着目前已经从远程仓库取下来的分支的末端版本;
  2. “git fetch”将:
    1. 更新“git remote”中所有远程仓库所包含分支的最新commit-id, 将其记录到“.git/FETCH_HEAD”文件中;
    2. 下载内容到“.git\objects”及“.git\refs”;
  3. git fetchgit pull
    1. git fetch拉取更新信息(commitID),但不会合并到本地工作目录;
    2. git pull将本地库更新至远程库的最新状态;

Note2:

  1. git fetch <远程主机名> <远程分支1> <远程分支2> <远程分支3>:从远程仓库拉取多个分支;
  2. git fetch <远程主机名> <远程分支>:拉取指定主机指定分支的更新;
  3. git fetch <远程主机名>:拉取指定主机的更新(不指定分支时通常默认为master);
  4. git fetch :拉取所有分支(branch)的更新;

Note3:

  1. 拉取分支更新,并在本地新建分支:
    • 不切换到该分支:
    1. git fetch <远程主机名> <远程分支>:<本地新建分支>
    • 并切换到该分支:
    1. git fetch <远程主机名> <远程分支>
    2. git checkout -b <本地新建分支> <远程主机名>/<远程分支>
  2. 拉取远程分支更新,并合并到本地分支(与git merge配合使用):
    1. git fetch origin master:从origin拉取分支master的更新;
    2. git merge origin/master:合并origin/master分支到当前分支
  3. 拉取多分支更新:
    1. 拉取多个分支:git fetch origin master stable oldstable,从远程仓库origin拉取master、stable、oldstable分支的更新;
    2. 合并多个分支:git merge origin/master hotfix-2275 hotfix-2276 hotfix-2290,合并origin/master、origin/stable、origin/oldstable到当前分支。

设置分支追踪关系

设置本地分支与远程分支的追踪关系,可以更方便地使用 git pull、git push 等命令。    ——如果是通过 git clone 建立的本地仓库,则已有追踪关系。

设置命令:

git branch --set-upstream-to=<remote>/<remote_branch> <local_branch>

日志

命令 说明 备注
git log 查看所有提交过的版本信息

Note1:

  1. git log --graph:查看分支commit关联拓扑图;
  2. git log --oneline:显示commit简略信息(只显示版本号前七位和提交时的备注信息);
    --pretty=oneline(显示完整版本号和备注);
  3. git log -5:显示过去5次提交;
  4. git log --reverse:逆序显示commit;
  5. git log --stat:显示commit历史,以及每次commit发生变更的文件;
  6. git shortlog -sn:显示所有提交过的用户,按提交次数排序;

Note2:

  1. git log --author=<pattern>:显示限定作者(正则表达式)的commit;
    --committer=<pattern>类似;
  2. git log --since=<date>:显示<date>之后的commit;
    --after=<date>--until=<date>--before=<date>类似;
git reflog 查看所有分支的所有操作记录

git blame 查看文件记录
  1. git blame <file>:查看指定文件的修改记录;

标签

tag实际就是一个指向commit的指针,将一个有意义的tag名称与commit相关联。
git标签有两种类型:

  1. 轻量级的(lightweight):实际上它就是个指向特定提交对象的引用。
  2. 含附注的(annotated):
    实际上是存储在仓库中的一个独立对象,有自身的校验和信息,包含标签名称,电子邮件地址和日期,及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
命令 说明 备注
git tag git标签

Note:

  1. git tag:查看所有标签;
  2. git tag <tagname>:创建标签(默认指定到当前分支);
  3. git tag <tagname> <commitID>:创建标签,并关联到指定分支;
  4. git tag -a <tagname>:创建带注解的标签(Git会打开编辑器来编辑tag的注解信息);
  5. git tag -d <tagname>:删除标签;
  6. git show <tagname>:查看tag关联的commit信息
  7. git tag -a <tagname> -m "标签信息":指定标签信息
  8. git tag -s <tagname> -m "标签信息":PGP签名标签

如:

Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation保留所有权利

D:\git\eijux>git tag

D:\git\eijux>git tag rc1.0

D:\git\eijux>git tag -a rc2.0

# Write a message for tag:
#   rc2.0
# Lines starting with '#' will be ignored.

D:\git\eijux>git tag rc3.0 ffa1

D:\git\eijux>git log --decorate
commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, tag: rc2.0, tag: rc1.0, eijux/master)
Author: Eijux <chen@eijux.com>
Date:   Fri Nov 1 01:18:47 2019 +0800

    idea commit test 01<E7><82><B9>18<E5><88><86>

commit ffa14211ab7088d9782de019328238dcfe09a4bc (tag: rc3.0)
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 16:03:24 2019 +0800

    Merge branch 'master' of github.com:Eijux/eijux

D:\git\eijux>git show rc3.0
commit ffa14211ab7088d9782de019328238dcfe09a4bc (tag: rc3.0)
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date:   Thu Oct 31 16:03:24 2019 +0800

    Merge branch 'master' of github.com:Eijux/eijux

D:\git\eijux>