git常用指令

新建仓库

git init

查看commit的操作日志

查看 reflog 记录

git reflog

输出可能如下所示:

b1e36d8 (HEAD -> master) HEAD@{0}: commit: Add new feature
4d5b7a2 HEAD@{1}: checkout: moving from feature to master
8a7c9f0 HEAD@{2}: commit: Fix bug in feature
9c7b2f1 HEAD@{3}: rebase -i (finish): returning to refs/heads/feature
e2b9d5c HEAD@{4}: checkout: moving from master to feature
  • 每一行表示一次引用的移动,包括操作类型和引用的位置。
  • HEAD@{n} 表示第 n 次操作的历史状态。

恢复丢失的提交
假设你误删除了某个提交,可以使用 reflog 找到并恢复它:

# 查看 reflog,找到需要恢复的提交哈希(例如 e2b9d5c)
git reflog

# 恢复到该提交
git checkout e2b9d5c

# 或者创建一个新的分支来保存恢复的提交
git branch recover-branch e2b9d5c

重置 HEAD 到特定的 reflog 位置
如果你想把 HEAD 重置到 reflog 中的某个位置,例如 HEAD@{3}:

git reset --hard HEAD@{3}

详细用途:

  1. 恢复误操作

    你可以使用 git reset --hard 或 git checkout 恢复到特定的提交,防止误操作导致的数据丢失。

  2. 找到分支的起始点

    有时候你可能需要找到一个分支的创建点,通过 reflog,你可以追溯到创建分支时的状态。

  3. 调试和修复历史

    在解决复杂问题时,reflog 提供了详细的操作记录,使你能够逐步回溯和调试。

注意事项:

  • reflog 记录的是本地仓库的操作,因此不会记录在远程仓库的引用变动。
  • reflog 数据会定期清理,默认情况下保留 90 天,因此对于长期追踪需要及时进行恢复操作。

总结
git reflog 是一个强大的工具,它记录了本地仓库引用的所有变动操作,帮助用户恢复丢失的提交、查看详细操作历史、调试复杂问题。熟练使用 reflog 可以极大地提高你对 Git 仓库的掌控能力,防止数据丢失和误操作。

添加文件到暂存区(stage)

git add .

.表示添加当前目录所有文件到暂存区

添加文件到本地仓库

git commit -m "comment for this commit"

查看已提交的commit

git log

查看工作区(working tree)文件的变化

git status

创建一条分支

  1. git branch newBranch

创建一条名为newBranch的分支

  1. git checkout -b newBranch

创建一条名为newBranch的分支,并且切换到该分支上

切换分支

git checkout newBranch

切换到名为newBranch的分支上

查看已有分支

git branch

合并两条分支

  1. git merge bugFix

假设当前在分支master上,该命令则表示创建一个新的commit。新的commit包含了bugFix和master的所有ancestor commits,并且将master移动到新的commit上

  1. git rebase bugFix

假设当前在分支master上,该命令表示copy所有在master上,但是不在bugFix上的commits到bugFix分支上,并且将master同步移动到bugFix最新commit之后,即在执行rebase之后,bugFix将成为master的ancestor commit(分支本质是一个指向某个commit的pointer)

比起mergerebase操作能够以线性的形式排列好repository的commits,让整个repository的修改记录看起来更加的清晰

git rebase <branch1> <branch2>该命令表示以branch1为基底将在branch2不在branch1的commits按顺序复制到branch1上,并且将branch2移动到最新的commit上

HEAD操作

  1. git checkout <commit>

Detaching HEAD just means attaching it to a commit instead of a branch. (将HEAD移动到某个commit)

  • 相对引用

    1. git checkout HEAD^

      将HEAD移动至上一个commit

    2. git checkout HEAD~<num>

      将HEAD移动至该commit往上的第<num>个commit

  • 相对引用相关的常用命令

    git branch -f main HEAD~3

    强制将branch main移动至HEAD往前的第3个commit

    Note: In a real git environment git branch -f command is not allowed for your current branch.

commit回滚(本地仓库)

  1. git reset HEAD^

回滚本地版本到上一个commit,跟上一个commit有差异的修改被存储在working place(PS: 使用git reset不加选项时,默认使用git reset --mixed模式,即将与上个commit的差异修改存在至working place)

  1. git reset HEAD~<num>

默认也是使用git reset --mixed模式,但是回滚<num>个commit

note:
git reset命令有三个主要的选项,它们可以用来调整当前分支的HEAD指针的位置以及它们对暂存区(index)和工作目录的影响。这些选项是:

--soft

--mixed

--hard

以下是每个选项的详细说明:

--soft

这个选项仅仅重置了HEAD到另一个commit,但是暂存区和工作目录的文件都不会被改变。如果你执行了--soft重置,之前提交的所有变化都会出现在暂存区,你可以重新提交这些变化。

git reset --soft

--mixed(默认选项)
当你不指定选项时,默认就是--mixed。这个选项会重置HEAD到指定的commit,并且也会重置暂存区以匹配那个commit。然而,工作目录中的文件不会被修改。这意味着之前的提交的变化会出现在工作目录,并且是未暂存的状态,你需要手动再次暂存它们。

git reset --mixed # 或者只用 git reset

--hard

这个选项是最危险的,因为它会重置HEAD到指定的commit,重置暂存区,并且也会重置工作目录中的文件。这意味着所有自上次commit之后的本地变更都将丢失。使用--hard选项时,你需要确保不会因此丢失工作目录中的重要更改。

git reset --hard

在使用git reset时,一定要小心,特别是使用--hard选项,因为如果你还没有备份你的工作,它可能会导致数据的永久丢失

commit回滚(远程仓库)

git revert HEAD^

git revert HEAD~<num>

git reset一样,不过git revert之后可以通过push,将回滚记录push到remote仓库,让其他人也可以看到回滚记录

给commit排序的git命令

  1. git cherry-pick <commit1> <commit2> <commit3> ...

按顺序将commit1,commit2,commit3复制到当前branch上

  1. git rebase -i <commit>

commit为基底,将其往后的commit排序重新生成一个commit sequence

修改某个commit的备注

1.xiu

  • 先通过git rebase -i <commit>将需要被修改备注的commit移动到最新的位置
  • git commit --amend修改备注
  • 通过git checkout <commit>先回到被选做基底的commit
  • git cherry-pick <commit>将需要被修改备注的commit移动到最新的位置
  • git commit --amend修改备注
  • 最后通过git cherry-pick <commit>将commit sequence恢复到原来的顺序

Note: Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't an ancestor of HEAD).

合并多个commit

git rebase -i <commit>

输入该命令后进入文本编辑器(命令中输入的commit往后一个commit至当前commit有效),根据文本编辑器提示进行commit合并即可

给某个版本加tag

  • 为什么需要tag?

Branches are easy to move around and often refer to different commits as work is completed on them. Branches are easily mutated, often temporary, and always changing.

Git tags support this exact use case -- they (somewhat) permanently mark certain commits as "milestones" that you can then reference like a branch.

More importantly though, they never move as more commits are created. You can't "check out" a tag and then complete work on that tag -- tags exist as anchors in the commit tree that designate certain spots.

分支很容易被人为移动,并且当有新的提交时,它也会移动。分支很容易被改变,大部分分支还只是临时的,并且还一直在变。

而Git 的 tag 可以解决这个问题,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。

更难得的是,它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。

当你通过git checkout <tag>命令切换到某个tag上,会进到分离 HEAD 的状态 —— 这是因为不能直接在上面做 commit。

当某个commit有多个parents,如何选择特定的parent

操作符 ^~ 符一样,后面也可以跟一个数字。

但是该操作符后面的数字与 ~ 后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的某个 parent 提交。还记得前面提到过的一个合并提交有两个 parent 提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。

远程分支强制推送

强制推送到远程分支是一个危险的操作,因为它会覆盖远程仓库中的分支,丢失所有自上次推送以来的改动。在你决定执行强制推送之前,请确保与你的团队成员沟通好,因为这可能会影响到他们正在进行的工作。

如果你确定需要进行强制推送,你可以使用下面的命令:

git push --force origin <branch_name>

或者,为了防止覆盖其他同时进行的推送操作,你可以使用带租(lease)的推送,它在远程分支没有新的提交时才会成功:

git push --force-with-lease origin <branch_name>

使用 --force-with-lease 选项比 --force 更安全,因为它会在远程分支有新的提交时阻止推送,避免覆盖别人的工作。

在进行强制推送时,再次提醒,务必确保你知道自己在做什么,并且已经与你的团队成员沟通过。强制推送会重写远程仓库的历史,这可能会导致其他开发者的本地历史与远程仓库的历史不一致,他们可能需要使用一些高级的Git技巧来同步更改。

克隆远程分支

git clone <remote-link>

设置远程仓库

git remote add <remote_name> <remote_url>

这里表示用<remote_name>代替远程仓库的url

推送本地分支到远程仓库

将分支推送到远程仓库。这会在远程仓库中创建一个新的分支,并建立本地分支与远程分支之间的跟踪关系:

git push -u origin <branch_name>

这里,-u 参数告诉Git设置上游(即远程跟踪)分支,这意味着以后当你在该分支上执行 git push 或 git pull 时,Git会知道默认使用哪个远程分支。

  • 推送本地仓库所有分支到远程仓库

git push origin --all

这个命令会将所有存在于本地的分支推送到名为 origin 的远程仓库。对于每个本地分支,如果远程分支不存在,它会在远程创建一个新的分支,并推送本地分支的所有提交。

请确保你拥有向远程仓库推送的权限,并且要知道这个操作可能会对其他使用远程仓库的人产生影响。通常在推送之前,最好执行 git fetch 来同步远程仓库的状态,并确保远程仓库是最新的。

生成commit的patch

  1. 要生成某个 commit 的 patch,可以使用 git format-patch 命令。假设你要生成最近一次 commit 的 patch,可以使用以下命令:

    git format-patch -1 <commit-hash>

    其中 <commit-hash>是你要生成 patch 的 commit 的哈希值。如果你想生成最新的 commit,可以使用 HEAD 代替 <commit-hash>

    例如:

    git format-patch -1 HEAD

  2. 如何用命令行的方式为本地仓库的每一个 commit 生成 patch

    如果你想为当前分支中的所有 commit 生成 patch,可以使用以下命令:

    git format-patch --root -o patches

    --root 选项表示从仓库的根 commit 开始生成 patch,-o patches 选项指定将生成的 patch 文件保存到 patches 目录中。

  3. 如何将 patch 导入仓库

    要将一个 patch 文件导入到当前分支,可以使用 git am 命令:

    git am <patch-file>

    其中<patch-file>是你要导入的 patch 文件的路径。

    例如:

    git am 0001-some-change.patch

  4. 如何将多个 patch 导入仓库

    要一次导入多个 patch 文件,可以使用 git am 命令并指定包含这些 patch 文件的目录:

    git am <patch-directory>/*.patch

    例如,如果所有 patch 文件都保存在 patches 目录中,你可以使用以下命令:

    git am patches/*.patch

    这将按顺序应用 patches 目录中的所有 patch 文件。

总结

以下是这些命令的示例用法:

  • 生成最近一次 commit 的 patch:

    git format-patch -1 HEAD

  • 为本地仓库的每一个 commit 生成 patch:

    git format-patch --root -o patches

  • 将单个 patch 导入仓库:

    git am 0001-some-change.patch

  • 将多个 patch 导入仓库:

    git am patches/*.patch

    通过这些命令,你可以方便地生成和应用 Git patch 文件,从而在不同的仓库或分支之间迁移更改。

git am 和 git apply的区别

使用 git apply 来导入 patch 文件是另一种方法,相比 git amgit apply 更接近于直接应用补丁到工作目录。以下是如何使用 git apply 命令导入 patch 文件的步骤。

  1. 将单个 patch 导入仓库

    首先,假设你有一个 patch 文件 0001-some-change.patch,可以使用以下命令来应用这个 patch:

    git apply <patch-file>

    例如:

    git apply 0001-some-change.patch

    这会将补丁内容应用到你的工作目录中,但不会自动创建一个新的 commit。

  2. 将多个 patch 导入仓库

    如果你有多个 patch 文件,可以使用通配符来一次性应用所有补丁:

    git apply <patch-directory>/*.patch

    例如,如果所有 patch 文件都保存在 patches 目录中,你可以使用以下命令:

    git apply patches/*.patch

  3. 创建 commit

    由于git apply只是将补丁内容应用到工作目录,你需要手动创建 commit 来保存这些更改。可以使用以下命令:

    git add .

    git commit -m "Apply patches"

    如果你希望每个 patch 对应一个单独的 commit,那么你需要逐个应用每个 patch 并创建相应的 commit:

      for patch in patches/*.patch; do
          git apply "$patch"
          git add .
          git commit -m "Apply patch $(basename "$patch")"
      done
  • 使用示例
  1. 应用单个 patch 并创建 commit:
git apply 0001-some-change.patch
git add .
git commit -m "Apply patch 0001-some-change"
  1. 一次性应用多个 patch 并创建一个 commit:
git apply patches/*.patch
git add .
git commit -m "Apply multiple patches"
  1. 逐个应用多个 patch 并为每个 patch 创建一个 commit:
for patch in patches/*.patch; do
  git apply "$patch"
  git add .
  git commit -m "Apply patch $(basename "$patch")"
done

总结

git apply提供了一种灵活的方法来应用 patch 文件,但与git am不同的是,它不会自动创建 commit。因此,当你需要精确控制 patch 的应用过程或将 patch 应用到未提交的更改时,git apply会更加适合。记得在应用 patch 后手动创建 commit 以保存更改。

分支重命名

git checkout old-branch // 切换到需要被重命名的分支
git branch -m new-branch // 输入命令,将new-branch更改成新分支的名字

强制分支A移动到分支B

git branch -f BranchA BranchB
posted @ 2024-04-24 17:42  stitchCat  阅读(40)  评论(0)    收藏  举报