编辑提交

查看当前HEAD最近一次提交

git show
# 或
git log -n1 -p

修改提交信息

# commit message 错误
git commit --amend --only -m "new message" # 如果已经push,可以修改这次提交然后强制push,但是多人项目不推荐。
# 用户名邮箱错误
git commit --amend --author "new author <[email protected]>

修改所有的历史,参考git ilter-branch命令。

从一个提交移除一个文件

git checkout HEAD^ <file>
git add -A
git commit --amend

如果已经push,可以修改然后强制push。

删除最后一次提交

# 已经push到远程仓库可以执行以下,这个多人项目不推荐,会造成已经拉取的用户的commit历史混乱
git reset HEAD^ --hard
git push -f <remote> <branch>
# 本地仓库没有推送到远程
git reset --soft [email protected]{1}

回滚本地以及远程仓库的提交

# 这个命令非常危险,一般不建议使用,尤其是多人项目
git reset <commit> --hard
git push -f origin HEAD 

删除任意提交

# 同样非常危险,一般不建议使用
git rebase --onto <bad commit>^ <bad commit>
git push -f <remote> <branch>

推送修改后的提交(amended commit)到远程仓库被拒绝

To https://github.com/yourusername/repo.git
! [rejected]        mybranch -> mybranch (non-fast-forward)
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

rebasing(见下面)和修正(amending)会用一个新的提交(commit)代替旧的,所以如果之前你已经往远程仓库上推过一次修正前的提交(commit),那你现在就必须强推(force push)。确保在同一个分支

git push -f <remote> <branch>

硬重置(hard reset)之后恢复

使用Git的时候需要知道一点,只要是commit了的内容,都会有日志记录,都是可以恢复的,可以通过git reflog查看,找到硬重置(git reset --hard)之前的commit,然后重新重置一次。

git reset --hard <commit>

清空所有的commit

# 这个命令有多危险我就不废话了
git update-ref -d HEAD

以新增一个commit的方式还原一个commit的修改

git revert <commit>

暂存

把暂存内容添加到上一次提交

git commit --amend

暂存一个新文件的一部分而不是全部

git add --patch <file> # -p 简写,针对已track文件,打开交互模式后使用s选项来分割提交
git add -N <file>      # untrach文件需要加-N,打开交互模式使用e选项手动选择添加的行

未暂存

未暂存的文件移动到新分支

git checkout -b <branch>

未暂存的文件到另一个已经存在的分支

git stash
git checkout <branch>
git stash pop

丢弃本地所有未提交的修改

git checkout -f

需要重置某个特殊文件

git reset <file>

分支

快速切换到上一个分支

git checkout -

删除已经合并的分支

git branch --merged | grep -v '*' | xargs -n 1 git branch -d

本地分支关联远程分支信息

git branch -vv

重命名本地分支

git branch -m <new name>

从错误的分支拉取了内容,或把内容拉取到了错误的分支

reflog大法好

git reflog # 获取错误之前的commit
git reset --hard <commit> # 然后硬重置到之前的commit

扔掉本地的提交,与远程分支保持一致

首先确定没有推送到远程仓库,git status会显示你领先(ahead)源(origin)多少个提交:

(master)$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#   (use "git push" to publish your local commits)
#

然后

git fetch --all && git reset --hard origin/master

提交更改到新分支,却错误提交到了master

git checkout <new branch> # 先基于当前的master创建一个新分支但切换过去
git reset --hard HEAD^    # 重置master到上一次提交
git checkout <new branch> # 检出新分支继续工作

不小心删除了分支

reflog大法好

git reflog # 查看删除操作之前的commit
git reset --hard <commit> # 然后硬重置到之前的commit

删除分支

# 删除远程分支
git push --delete <remote> <branch>
# 或
git push <remote> :<branch>
# 删除本地分支
git branch -D <branch>

从别人正在工作的远程分支检出一个分支

首先,从远程分支拉取所有分支

git fetch --all

然后从远程分支检出到本地分支

git checkout --track origin/<branch>
# --trach 是git checkout -b <branch> <remote>/<branch>的简写

合并

撤销rebase或merge

Git在进行危险操作的时候会把原始的HEAD保存在一个叫ORIG_HEAD的变量里。无论是用rebase还是merge进行合并,合并了一个错误的分支, 或者完成不了一个进行中的合并,都可以把分支恢复到rebase/merge前的状态。

git reset --hard ORIG_HEAD

安全merge策略

git merge --no-ff --no-commit <branch>
# --no-commit 执行合并(merge)但不自动提交, 给用户在做提交前检查和修改的机会
# --no-ff 会为特性分支(feature branch)的存在过留下证据, 保持项目历史一致

其他

clone所有子模块

git clone --recursive <url>

如果已经克隆,需要更新的话

git submodule update --init --recursive

从stash拿出某个文件

git checkout <[email protected]{n}> -- <file>

把某一个分支导出为文件

git bundle create <bundle-file> <branch>

导入

git clone <bundle-file> <repo> -b <branch>

执行rebase之前自动stash

git rebase --autostash

详细展示一行中的差异

git diff --word-diff

清除满足gitignore中模式的文件

git clean -X -f

显示branch1有branch2没有的commit

git log <branch1> ^<branch2>

clone指定分支

git clone -b <branch> --single-branch <url>

恢复已删除的tag

先找到无法访问的tag,记下哈希值

git fsck --unreachable | grep tag

然后进行恢复

git update-ref refs/tags/<tag> <hash>

从Git中删除文件,但保留该文件在当前目录

git rm --cached <file>

总之,reflog大法好。

参考资料