哎呦我去,Git 竟然可以這么用?!!
用好 Git 很難: 很容易就犯錯了,然后想自己彌補犯下的錯,簡直太難了。
查閱 Git 文檔簡直就像是個 “雞生蛋 蛋生雞” 的問題,你得知道你要的是啥 ,但如果我知道的話,我還 tm 查個毛文檔??!
所以接下來我會分享一些我遇到過的抓狂的經歷,然后用大白話來說說我是如何解決的。
哎呦我去,我剛才好像犯了個大錯,能不能給我臺時光機啊!?!
git reflog# 你將看到你在 git 上提交的所有改動記錄被列# 了出來,而且囊括了所有的分支,和已被刪除的# commit 哦!# 每一條記錄都有一個類似 HEAD@{index} 的索# 引編號# 找到在犯錯前的那個提交記錄的索引號,然后執(zhí)# 行:git reset HEAD@{index}# 哈哈,這就是你要的時光機!
你可以用這個方法來找回那些你不小心刪除的東西、恢復一些你對 repo 改動、恢復一次錯誤的 merge 操作、或者僅僅想退回到你的項目還能正常工作的那一時刻。我經常使用 reflog,在此我要向那些提案添加這個功能的人們表示感謝,太謝謝他們了!
哎呦我去,我剛提交 commit 就發(fā)現還有一個小改動需要添加!
# 繼續(xù)改動你的文件git add . # 或者你可以添加指定的文件git commit --amend --no-edit# 你這次的改動會被添加進最近一次的 commit 中# 警告: 千萬別對公共的 commit 做這種操作
這經常發(fā)生在我提交了 commit 以后立馬發(fā)現,媽蛋,我忘了在某個等號后面加空格了。當然,你也可以提交一個新的 commit 然后利用 rebase -i 命令來合并它們,但我覺得我的這種方式比你快 100 萬倍。
警告: 你千萬不要在已推送的公共分支上做這個 amend 的操作! 只能在你本地 commit 上做這種修改,否則你會把事情搞砸的!
哎呦我去,我要修改我剛剛 commit 提交的信息!
git commit --amend# 按照提示修改信息就行啦
哎呦我去,我不小心把本應在新分支上提交的東西提交到了 master!
# 基于當前 master 新建一個分支git branch some-new-branch-name# 在 master 上刪除最近的那次 commitgit reset HEAD~ --hardgit checkout some-new-branch-name# 只有在這個新分支上才有你最近的那次 commit 哦
注意:如果你已將這個 commit 推送到了公共分支,那這波操作就不起作用了。如果你在此之前做了些其他的操作,那你可能需要使用 HEAD@{number-of-commits-back} 來替代 HEAD~。另外,感謝很多人提出了這個我自己都不知道的超棒的解決方法,謝謝大家!
哎呦我去,我把這個 commit 提交錯分支了!
# 撤回這次提交,但保留改動的內容git reset HEAD~ --softgit stash# 現在切到正確的那個分支去git checkout name-of-the-correct-branchgit stash popgit add . # 或者你可以添加指定的文件git commit -m "your message here";# 現在你的改動就在正確的分支上啦
很多人建議使用 cherry-pick 來解決這個問題,其實兩者都可以,你只要選擇自己喜歡的方式就行了。
git checkout name-of-the-correct-branch# 抓取 master 分支上最新的那個 commitgit cherry-pick master# 然后刪掉 master 上的那個 commitgit checkout mastergit reset HEAD~ --hard
哎呦我去,我想用 diff 命令看下改動內容,但啥都沒看到?!
如果對文件做了改動,但是通過 diff 命令卻看不到,那很可能是你執(zhí)行過 add 命令將文件改動添加到了 暫存區(qū) 了。你需要添加下面這個參數。
git diff --staged這些文件在這里 ˉ_(ツ)_/ˉ (是的,我知道這是一個 feature 而不是 bug,但它第一次發(fā)生在作為初學者的你身上時,真的很讓人困惑!)
哎呦我去,我想撤回一個很早以前的 commit!
# 先找到你想撤銷的那個 commitgit log# 如果在第一屏沒找到你需要的那個 commit,可以用上下# 箭頭來滾動顯示的內容,找到了以后記下 commit 的# hash 值git revert [剛才記下的那個 hash 值]# git 會自動修改文件來抵消那次 commit 的改動,并創(chuàng)# 建一個新的 commit,你可以根據提示修改這個新 commit# 的信息,或者直接保存就完事了
這樣你就不需要用回溯老版本然后再復制粘貼的方式了,那樣做太費事了!如果你提交的某個 commit 導致了 bug,你直接用 revert 命令來撤回那次提交就行啦。
你甚至可以恢復單個文件而不是一整個 commit!但那是另一套 git 命令咯...
哎呦我去,我想撤回某一個文件的改動!
# 找到文件改動前的那個 commitgit log# 如果在第一屏沒找到你需要的那個 commit,可以用上下# 箭頭來滾動顯示的內容,找到了以后記下 commit 的# hash 值git checkout [剛才記下的那個 hash 值] -- path/to/file# 改動前的文件會保存到你的暫存區(qū)git commit -m "這樣就不需要通過復制粘貼來撤回改動啦"
我花了好長好長,真他媽長的時間才搞明白要這么做。說真的,用 checkout -- 來撤回一個文件的改動,這算什么鬼方式啊?! :向 Linus Torvalds 擺出抗議姿勢:
去*吧,這些亂七八糟煩人的文件, 我放棄啦。(那些 untracked 的文件)
cd ..sudo rm -r fucking-git-repo-dirgit clone https://some.github.url/fucking-git-repo-dir.gitcd fucking-git-repo-dir
感謝 Eric V. 提供了這個事例,如果對 sudo 的使用有什么的質疑的話,可以去向他提出。
不過說真的,如果你的分支真的這么糟糕的話,你應該使用 "git-approved" 的方法來重置你的 repo,可以試試這么做,但要注意這些操作都是破壞性的,不可逆的!
# 獲取遠端庫最新的狀態(tài)git fetch origingit checkout mastergit reset --hard origin/master# 刪除 untracked 的文件和目錄git clean -d --force# 對每一個有問題的分支重復上述 checkout/reset/clean 操作
長按識別下圖二維碼,關注公眾號「Doocs 開源社區(qū)」,第一時間跟你們分享好玩、實用的技術文章與業(yè)內最新資訊。
