# Git飞行规则 #### 什么是"飞行规则" > *飞行规则(Flight Rules)* 是记录在手册上的来之不易的一系列知识,记录了某个事情发生的原因,以及怎样一步一步的进行处理。本质上, 它们是特定场景的非常详细的标准处理流程 ### 我刚才提交了什么 ```sh git show ``` ```sh git log -n1 -p ``` ### 我的提交信息写错了 如果提交信息写错了且这次提交还没有push ```sh git commit --amend --only ``` ```sh git commit --amend --only -m 'xxxxxxx' ``` ### 我提交的用户名和邮箱不对 ```sh git commit --amend --author "New Authorname " ``` ### 我想从一个提交里移除一个文件 ```sh git checkout HEAD^ myfile git add -A git commit --amend ``` ### 我想删除我的的最后一次提交 如果你需要删除push了的提交。 ```sh git reset HEAD^ --hard git push -f [remote] [branch] ``` 如果你还没有推到远程, reset到最后一次提交前的状态 ``` git reset --soft HEAD@{1} ``` 如果已经push了, 唯一安全的是 `git revert SHAofBadCommit` ### 删除任意提交 尽量不要这么做. ```sh git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT git push -f [remote] [branch] ``` ### 我意外的做了一次hard reset,我想找回我的内容 ```sh git reflog ``` ```sh git reset --hard SHA1234 ``` ## 暂存 ### 我需要把暂存的内容添加到上一次的提交 ```sh git commit --amend ``` ### 我想要暂存一个新文件的一部分,而不是这个文件的全部 ```sh git add --patch filename.x ``` `-p` 会打开交互模式, 你将能够用 `s` 选项来分隔提交(commit); 然而, 如果这个文件是新的, 会没有这个选择, 添加一个新文件时, ```sh git add -N filename.x ``` 然后, 你需要用 `e` 选项来手动选择需要添加的行,执行 `git diff --cached` 将会显示哪些行暂存了哪些行只是保存在本地。 ### 我想把在一个文件里的变化(changes)加到两个提交里 `git add` 会把整个文件加入到一个提交. `git add -p` 允许交互式的选择你想要提交的部分. ## 未暂存的内容 ### 我想把未暂存的内容移动到一个新分支 ```sh git checkout -b my-branch ``` ### 我想把未暂存的内容移动到另一个已存在的分支 ```sh git stash git checkout my-branch git stash pop ``` ### 我想丢弃本地未提交的变化 如果你只是想重置源(origin)和你本地(local)之间的一些提交,你可以: ```sh # one commit git reset --hard HEAD^ # two commits git reset --hard HEAD^^ # four commits git reset --hard HEAD~4 # or git checkout -f ``` 重置某个特殊的文件, 用文件名做为参数: ```sh $ git reset filename ``` ## 分支 ### 我从错误的分支拉取了内容,或把内容拉取到了错误的分支 ```sh git reflog ab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward c5bc55a HEAD@{1}: checkout: checkout message goes here ``` 重置分支到所需的提交 ```sh git reset --hard c5bc55a ``` ### 我想扔掉本地的提交,以便我的分支与远程的保持一致 `git status` 会显示你领先源多少个提交: ```sh git status # On branch my-branch # Your branch is ahead of 'origin/my-branch' by 2 commits. # (use "git push" to publish your local commits) # ``` ```sh git reset --hard origin/my-branch ``` ### 我需要提交到一个新分支,但错误的提交到了main 在main下创建一个新分支,不切换到新分支,仍在main下: ```sh git branch my-branch ``` 把main分支重置到前一个提交: ```sh git reset --hard HEAD^ ``` 或者, 如果不使用 `HEAD^`, 找到想重置到的提交的hash(`git log` ), 然后重置到这个hash。 使用`git push` 同步内容到远程。 例如, main分支想重置到的提交的hash为`a13b85e`: ```sh git reset --hard a13b85e HEAD is now at a13b85e ``` checkout刚才新建的分支继续工作: ```sh git checkout my-branch ``` ### 我不小心删除了我的分支 如果定期推送到远程, 多数情况下应该是安全的,但有些时候还是可能删除了还没有推到远程的分支。 先创建一个分支和一个新的文件: ```sh git checkout -b my-branch git branch touch foo.txt ls README.md foo.txt ``` 添加文件并做一次提交 ```sh git add . git commit -m 'foo.txt added' (my-branch)$ foo.txt added 1 files changed, 1 insertions(+) create mode 100644 foo.txt git log commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012 Author: siemiatj Date: Wed Jul 30 00:34:10 2014 +0200 foo.txt added commit 69204cdf0acbab201619d95ad8295928e7f411d5 Author: Kate Hudson Date: Tue Jul 29 13:14:46 2014 -0400 Fixes #6: Force pushing after amending commits ``` 现在我们切回到主分支,不小心的’删除`my-branch`分支 ```sh git checkout main Switched to branch 'main' Your branch is up-to-date with 'origin/main'. git branch -D my-branch Deleted branch my-branch (was 4e3cd85). echo oh noes, deleted my branch! oh noes, deleted my branch! ``` ``` git reflog 69204cd HEAD@{0}: checkout: moving from my-branch to main 4e3cd85 HEAD@{1}: commit: foo.txt added 69204cd HEAD@{2}: checkout: moving from main to my-branch ``` ```sh git checkout -b my-branch-help Switched to a new branch 'my-branch-help' git reset --hard 4e3cd85 HEAD is now at 4e3cd85 foo.txt added ls README.md foo.txt ``` ### 我想删除一个分支 删除一个远程分支: ```sh git push origin --delete my-branch ``` 也可以: ```sh git push origin :my-branch ``` ## Rebasing 和合并 ### 我想撤销rebase/merge 当完成不了一个进行中的rebase/merge,Git 在进行危险操作的时候会把原始的HEAD保存在一个叫ORIG_HEAD的变量里 ```sh git reset --hard ORIG_HEAD ``` #### 安全合并策略 `--no-commit` 执行合并但不自动提交, 给用户在做提交前检查和修改的机会。 `no-ff` 会为特性分支的存在过留下证据, 保持项目历史一致。 ```sh git merge --no-ff --no-commit my-branch ``` #### 我需要将一个分支合并成一个提交 ```sh git merge --squash my-branch ``` ### 检查是否分支上的所有提交都合并过了 在这些分支的head(或任何 commits)之间做一次diff: ```sh git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll ``` 另一个做法 ```sh git log main ^feature/120-on-scroll --no-merges ``` ## Stash ### 暂存所有改动 ```sh git stash ``` `-u`排除一些文件 ```sh git stash -u ``` ### 暂存指定文件 ```sh git stash push working-directory-path/filename.ext ``` ```sh git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext ``` ### 暂存时记录消息 这样你可以在`list`时看到它 ```sh git stash save ``` 或 ```sh git stash push -m ``` ### 使用某个指定暂存 ```sh git stash list ``` ```sh git stash apply "stash@{n}" ``` ### 暂存时保留未暂存的内容 手动create一个`stash commit`, 然后使用`git stash store`。 ```sh git stash create git stash store -m "commit-message" CREATED_SHA1 ```