... 来丢弃文件的修改
$git checkout -- createGraph.py
这样就恢复了 rm 了的文件
- $ls
- createGraph.py
解决方案 2:
- git rm README
- git status
- $ git stash list
- stash@{0}: WIP on master: bfcdf14 test git
- # 拿出来使用 git stash pop
- git stash pop
[Git 高级教程: git stash]
解决方案 3:
这时可以直接使用 git log; git reset --hard "commit id" 恢复到上一个 commit, 但是这样不好, 我只想恢复删除的那一个文件, 要是 commit 之间做了很多改动, 恢复到上一个 commit 会将其它文件的修改都恢复了要对单个文件修改
首先查看该文件的历史版本信息: git log?Default@2x.png
记录下需要恢复的 commit 版本号: 如? 9aa51d89799716aa68cff3f30c26f8815408e926
恢复该文件: git reset 9aa51d89799716aa68cff3f30c26f8815408e926?Default@2x.png
提交 git:git commit -m "revert old file"
测试了一下, 发现文件根本没有改动, 只是有 unstaged commit 的提示(说明一下, 我是在 windows 环境下使用 git 客户端, linux 不知道是不是同样的问题), 并且, 一旦执行 git add ., 所有暂存区中的变化全都消失了
尝试执行 git checkout 命令, 因为这个命令平时只适应于将文件恢复到上次递交的状态, 而不能选择递交的版本
虽然执行完毕后什么提示都没, 但是查看文件可以看到, 文件已经被修改为历史版本了
总结: git 将单个文件恢复到历史版本的正确方法如下:
? ?git reset commit_id 文件路径
? ?git checkout -- 文件路径
[?GIT 恢复单个文件到历史版本]
皮皮 Blog
版本回退 - 撤销文件修改
{针对文件修改恢复}
工作区修改一个文件后, 又想回到修改前(git add 前)
1. 当然可以直接手动再在工作区中将文件修改回去
2. 修改后, 通过命令 git status 查看
- $ git status
- # On branch master
- # Changes not staged for commit:
- # (use "git add ..." to update what will be committed)
- # (use "git checkout -- ..." to discard changes in working directory)
- #
- # modified: readme.txt
- #
- no changes added to commit (use "git add" and/or "git commit -a")
这时 Git 会告诉你, git checkout -- file 可以丢弃工作区的修改:
- $ git checkout -- readme.txt
- Note:
1. git checkout -- file 命令中的 -- 很重要, 没有 --, 就变成了切换到另一个分支的命令, 我们在后面的分支管理中会再次遇到 git checkout 命令
2. 命令 git checkout -- readme.txt 意思就是, 把 readme.txt 文件在工作区的修改全部撤销, 这里有两种情况:
一种是 readme.txt 自修改后还没有被放到暂存区, 现在, 撤销修改就回到和版本库一模一样的状态; 一种是 readme.txt 已经添加到暂存区后, 又作了修改, 现在, 撤销修改就回到添加到暂存区后的状态总之, 就是让这个文件回到最近一次 git commit 或 git add 时的状态
3.? 工作区暂存区的概念不清楚的可见于 Git 版本控制教程 - Git 本地仓库
如果在工作区中修改了文件还 git add 到暂存区(但是在 commit 之前)
用 git status 查看一下, 修改只是添加到了暂存区, 还没有提交:
- $ git status
- # On branch master
- # Changes to be committed:
- # (use "git reset HEAD ..." to unstage)
- #
- # modified: readme.txt
- #
Git 同样告诉我们, 用命令 git reset HEAD file 可以把暂存区的修改撤销掉(unstage), 重新放回工作区:
- $ git reset HEAD readme.txt
- Unstaged changes after reset:
- M readme.txt
git reset 命令既可以回退版本, 也可以把暂存区的修改回退到工作区当我们用 HEAD 时, 表示最新的版本
再用 git status 查看一下, 现在暂存区是干净的, 工作区有修改
然后丢弃工作区的修改
- $ git checkout -- readme.txt
- $ git status
- # On branch master
- nothing to commit (working directory clean)
不但修改了文件还从暂存区提交 commit 到了版本库 - 版本回退
版本回退可以回退到上一个版本不过, 这是有条件的, 就是你还没有把自己的本地版本库推送到远程 Git 是分布式版本控制系统
在工作中对某个文件 (如 readme.txt) 进行多次修改交 commit
可以通过版本控制系统命令告诉我们提交的历史记录, 在 Git 中, 我们用 git log 命令查看:
- $ git log
- commit 3628164fb26d48395383f8f31179f24e0882e1e0
- Author: Michael Liao
- Date: Tue Aug 20 15:11:49 2013 +0800
- append GPL
- commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
- Author: Michael Liao
- Date: Tue Aug 20 14:53:12 2013 +0800
- add distributed
- commit cb926e7ea50ad11b8f9e909c05226233bf755030
- Author: Michael Liao
- Date: Mon Aug 19 17:51:55 2013 +0800
- wrote a readme file
- Note:
1.?git log 命令显示从最近到最远的提交日志, 我们可以看到 3 次提交, 最近的一次是 append GPL, 上一次是 add distributed, 最早的一次是 wrote a readme file
2. 如果嫌输出信息太多, 看得眼花缭乱的, 可以试试加上 --pretty=oneline 参数:
- $ git log --pretty=oneline
- 3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
- ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
- cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
3.? 你看到的一大串类似 3628164...882e1e0 的是 commit id(版本号), 和 SVN 不一样, Git 的 commit id 不是 1,2,3 递增的数字, 而是一个 SHA1 计算出来的一个非常大的数字, 用十六进制表示, 而且你看到的 commit id 和我的肯定不一样, 以你自己的为准为什么 commit id 需要用这么一大串数字表示呢? 因为 Git 是分布式的版本控制系统, 后面我们还要研究多人在同一个版本库里工作, 如果大家都用 1,2,3 作为版本号, 那肯定就冲突了
4.? 每提交一个新版本, 实际上 Git 就会把它们自动串成一条时间线如果使用可视化工具 (如 GitXgithub 的客户端 pycharm) 查看 Git 历史, 就可以更清楚地看到提交历史的时间线 0
现在我们想要把 readme.txt 回退到上一个版本
如 add distributed 的那个版本, 怎么做呢? 首先, Git 必须知道当前版本是哪个版本, 在 Git 中, 用 HEAD 表示当前版本, 也就是最新的提交 3628164...882e1e0(注意我的提交 ID 和你的肯定不一样), 上一个版本就是 HEAD^, 上上一个版本就是 HEAD^^, 当然往上 100 个版本写 100 个 ^ 比较容易数不过来, 所以写成 HEAD~100
现在, 我们要把当前版本 append GPL 回退到上一个版本 add distributed, 就可以使用 git reset 命令:
- $ git reset --hard HEAD^
- HEAD is now at ea34578 add distributed
这时 readme.txt 的内容就成了版本 add distributed 我们用 git log 再看看现在版本库的状态:
- $ git log
- commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
- Author: Michael Liao
- Date: Tue Aug 20 14:53:12 2013 +0800
- add distributed
- commit cb926e7ea50ad11b8f9e909c05226233bf755030
- Author: Michael Liao
- Date: Mon Aug 19 17:51:55 2013 +0800
- wrote a readme file
最新的那个版本 append GPL 已经看不到了!
恢复文件后, 要是我们又想回到修改后的文件呢?(命令行窗口还没有被关掉)
{这个是 git reset --hard 后, 又反悔了, 想回到修改后的状态}
只要上面的命令行窗口还没有被关掉, 你就可以顺着往上找啊找啊, 找到那个 append GPL 的 commit id 是 3628164..., 于是就可以指定回到未来的某个版本:
- $ git reset --hard 3628164
- HEAD is now at 3628164 append GPL
版本号没必要写全, 前几位就可以了, Git 会自动去找
Git 的版本回退速度非常快, 因为 Git 在内部有个指向当前版本的 HEAD 指针, 当你回退版本的时候, Git 仅仅是把 HEAD 从指向 append GPL:
改为指向 add distributed:
然后顺便把工作区的文件更新了所以你让 HEAD 指向哪个版本号, 你就把当前版本定位在哪
恢复文件后, 要是我们又想回到修改后的文件呢?(命令行窗口早就关掉了)
{这个是 git reset --hard 后, 又反悔了, 想回到修改后的状态}
想恢复到新版本怎么办? 找不到新版本的 commit id 怎么办? 当你用 $ git reset --hard HEAD^ 回退到 add distributed 版本时, 再想恢复到 append GPL, 就必须找到 append GPL 的 commit id
Git 提供了一个命令 git reflog 用来记录你的每一次命令:[Git 高级教程: git log 与 git reflog]
- $ git reflog
- ea34578 HEAD@{0}: reset: moving to HEAD^
- 3628164 HEAD@{1}: commit: append GPL
- ea34578 HEAD@{2}: commit: add distributed
- cb926e7 HEAD@{3}: commit (initial): wrote a readme file
第二行显示 append GPL 的 commit id 是 3628164, 现在, 你又可以乘坐时光机回到未来了
git 撤销文件追踪
git 忽略已经被提交的文件 / 文件夹
{git 对于 已经添加到版本库的文件设置忽略}
问题
git commit 时候忘记设置 ignore 了, 于是 commit 了一个相当大的文件, git push 时候, 因为要 push 大文件, 可能会出错, 也可能 push 好久还没好 如果直接删除掉大文件, 再 push 还是同样问题; 如果把大文件放到忽略文件里, 再 push, 还是这样的问题不变
几种解决方案:
终极解决方案 1
适用于这个文件是最近一次 commit 的, 并且 git commit 的其它内容 (如小文件) 也回退
一旦发现 git push 了大文件失败了, 就使用下面命令回退这次 commit, 再添加. gitignore 再 add 和 commit
git reset? --mixed(默认) : 取消了 commit , 取消了 addYour branch is ahead of 'origin/master' by 1 commit. 不小心 commit 大文件, 但是 push 失败, 使用 git log 找到上一次的版本号, 再使用 git reset --mixed 版本号就可以了
终极解决方案 2
git 当 push100M 以上文件, 就直接拒绝你的 push, 要想 push 必须把该文件从本地仓库和远程仓库全部移除到 commit 外
注意此方法适用于这个文件是最近一次 commit 的 {包括已经 push 到 github 了(所以要先 git pull)} 并且希望 git commit 的其它内容 (如小文件) 不回退
git rm --cached /XXX/XXX/libbaiduNaviSDK.a(加下划线部分是你自己的要移除的文件的路径)
- find . -size +100M ! -path "*git*" | xargs git rm --cached
- git commit --amend -CHEAD
- find . -size +100M ! -path "*git*" | mv /tmp/tmpgit
- git pull
- git push
下次再 add 时
先添加大文件到. gitignore
mv /tmp/tmpgit .
再 git add .
- git commit -m 'del -size +100M'
- git push
- Note:
第一步: 将文件从暂存区去除;
第二步: 是修改提交, 也就是用这次删除了大文件的暂存区的新的 commit 覆盖上次大文件的 commit;
第三步: 移除之前的大文件(或者是想删除之前 commit 上的文件);
第四步: 如果不执行干什么都会提示: On branch master Your branch and 'origin/master' have perged,and have 1 and 1 different commits each, respectively.? (use "git pull" to merge the remote branch into yours)nothing to commit, working tree clean
第五步: 添加大文件不加入 git 版本控制
第七步: commit
执行完这步后, 这个大文件将会从你的 commit 记录里和 add 移除(也就是不会再出现在 stage 暂存区或者 master 中, 这些大于 100M 的文件会回到 git add . 之前的状态, 相当于没有 git add, 成为 untracked files), 这时候就可以 git push 把本地代码 push 到 github 上了
记得加. ignore 或者回到 git lfs 中来上传大文件![Git 版本控制: Git 高级教程]
- [Removing a file added in the most recent unpushed commit]
- [Working with large files]
如果是前几次提交的 git commit 了大文件, 这时上面的修改可能包含了对大文件的处理过程(这样就可逆对大文件的 commit 了?), 还是会上传对大文件的修改如:
- $ git diff origin/master --name-statusA?????? JIM/business_result.json #并没有大文件会 push
- A?????? JIM/yelp_academic_dataset_business.json
- A?????? JIM/yelp_academic_dataset_tip.json
但是 git push 时怎么还是上传的这个大文件, 这难道是因为 git diff 比较的只是当前 commit 和远程, 而本地实际有两个 commit 版本, 大文件存在于前一个版本中, 所以只要有就会上传
- remote: error: Trace: 4cbb68625000edd0054cf593be3f7058 remote: error: See https: //git.io/iEPt8g for more information.
- remote: error: File JIM / test_candidate.dat is 188.52 MB;
- this exceeds GitHub 's file size limit of 100.00 MB'
这时只能使用下面的终极解决方案 2 了, 前本地 commit 所有版本中的大文件都 del 掉
终极解决方案 3
此方法适用于这个文件是前几次 commit 的
git filter-branch --tree-filter
如 commit 了一个 EpipeCpu/ipch 目录下的大文件, 现在要 push 但是仅想删去 commit 中的这个目录
- $git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch 大文件目录或名字 -r' --prune-empty --tag-name-filter cat -- --all
- Rewrite 44a7e4ad5e52ff26306338fbba9a890c50ba9ba7 (1/1) (0 seconds passed, remaining 0 predicted)??
- rm 'EpipeCpu/ipch/algorithms-5512fb35/algorithms-c0d91126.ipch'
- rm 'EpipeCpu/ipch/epipecpu-63fefe78/epipecpu-e9527547.ipch'
- Ref 'refs/heads/master' was rewritten
再使用 git push 就不会上传那个目录下的文件了
当然 lz 也将这个目录加入到了 exclude 中(之前 git commit 忘了加的)
不过此方法有可能会带来一些问题
一定要尽可能少用这个功能, 虽然他可以减少我们 git 目录的大小, 但是这会对其他协作者产生极大的影响所有受到影响的 commit 的 ID 都会被重写, 另外如果 commit 像我这样有 GPG 签名的话, 就无法执行这个操作了
[从 git commit 中永久删除某个文件]
[如何删除 github 上的一个项目的内容, 重新提交所有内容]
使用 git reset 回滚 commit 操作
像上面撤销文件修改那样 git reset 操作解决 但是如果是 commit 很多次提交后才发现 commit 了大文件, 回滚到大文件之前的同时也回滚了不想回滚的其它 commit, 这样不好 并且这样有可能 git reset 操作之后有时候还是会提交上次提交失败的大文件, 可能还在上一个 commit 中大文件没有 ignore(这个是通过 git diff origin/dev...HEAD --name-status 查到大文件还是会上传 push 看到的),git reset 方法似乎不是最保险
使用 git rm --cached
{这个删除了还是要上传的, 不知道为嘛, 可能是因为: git rm --cached will add the delete action of the file to the index, just like git add will add an add action. 也就是说还是会添加这个文件到远程, 然后再删除, 不是坑吗... 不过 lz 觉得这个方法只能用在 git add . 后并且在 git commit 之前}
有下面的另一种方法, 即不是回退, 而是将 commit 后的文件直接从 commit 中删除掉, 这样就不用管是哪次的 commit 出了大文件错误问题了 Git 取消跟踪某个文件: git commit 某个文件后又不想跟踪它了(比如取消已经 commit 的大文件, 不想 push 到远程), 可以通过下面的方法解决
$git rm --cached FILENAME
如果后面跟的是目录就加上个 -r ? 就行,(这个操作不会删除这个文件)git rm -r --cached DIR_NAME
然后更新 info/exclude 或者. gitignore 忽略掉目标文件, 不知道怎么操作的可参见[Git 版本控制教程 - Git 本地仓库: 忽略指定文件]
最后? git commit -m "dont track"?? ? 还是? git commit --amend -CHEAD?? 成功之后会提示: ... * file changed ... delete mode ... FILENAME 检查一下, git status, 提示 nothing commit... 就说明成功删除文件的追踪如果显示 untracked file FILENAME, 可能是 ignore 文件出错, 解决参见[Git 版本控制教程 - Git 本地仓库: 忽略指定文件] 当然如果你后悔了, 从 ignore 文件中删除 FILENAME, 再直接 git add . 就可以了, 然后 git commit, 可能会提示没有什么变化 [.gitignore not working] [处理 GitHub 不允许上传大于 100M 文件问题] [git 忽略已经被提交的文件]
究极解决方案: 本地重建并取代远程
lz 碰到一个很烦人的, git rm --cached bigfile 并且 ignore 后, 使用 git diff 查看明明没有大文件, 所有要提交的大文件都是 D(delete 模式), 难道 delete 的文件也要上传? 还是之前 add 大文件后再 git rm cached 后有两个操作, add 再 delete, 可是 git diff 里面并没有 add 大文件, 不知道为什么总是有那个大文件上传, 总是! 用了无数方法总是有这个大文件 targetopinion/dist/TargetOpinionMain.exe: git diff 查看是没有 TargetOpinionMain.exe 文件 add 的, 也是奇怪 ps:lz 曾经将这个大文件从 nlp/dist 移动到 nlp/targetopinion/dist 中, 然后路径中 git rm --cached 不能作用于 dist, 而可以作用于 targetopinion/dist, 但是怎么说那个 targetopinion/dist 中的 exe 大文件是没有的! 可是它总是有! 搞了好久, lz 只能采取下面的极限方法了: 删除本地 nlp 目录下的. git 文件夹 重新设置本地 git 管理: git init git remote add origin git@github.com:*** git add . git commit -m 'init commit' git push -u --force origin 分支名 这里是强制提交, 本来要 git pull 的, 但是这样可能覆盖本地文件, 要是完全不想要远程的文件了, 可以这样, 用本地取代远程的文件(结果导致远程主机上更新的版本被覆盖)git push 见[Git 版本控制教程 - Git 远程仓库:--force 选项] 这个其实不就是如何删除 github 上的一个项目的内容, 重新提交所有内容吗?[如何删除 github 上的一个项目的内容, 重新提交所有内容]
修改最后一次提交 git commit --amend
{还有一种有条件但是更简单快捷的解决方案: git commit --amend 修改上一次的提交信息, 这是最快最好的方法, 不过如果不是针对上一次提交那就不好了!} 有时候用 git commit -m 提交时, 可能没写好或者误操作导致提交的信息不合适, 但你还没有 push 到远程分支时, 可以使用 git commit --amend 修改上一次的提交信息 有时候我们提交完了才发现漏掉了几个文件没有加, 或者提交信息写错了想要撤消刚才的提交操作, 可以使用 --amend 选项重新提交:
$ git commit --amend
此命令将使用当前的暂存区域快照提交如果刚才提交完没有作任何改动, 直接运行此命令的话, 相当于有机会重新编辑提交说明, 但将要提交的文件快照和之前的一样
启动文本编辑器后, 会看到上次提交时的说明, 编辑它确认没问题后保存退出, 就会使用新的提交说明覆盖刚才失误的提交
如果刚才提交时忘了暂存某些修改, 可以先补上暂存操作, 然后再运行 --amend 提交:
- $ git commit -m 'initial commit'
- $ git add forgotten_file
- $ git commit --amend
上面的三条命令最终只是产生一个提交, 第二个提交命令修正了第一个的提交内容
[git commit amend 修改还未提交到远程分支的 commit 信息]
git?update-index
这种方法好像有问题, 不推荐 git update-index --assume-unchanged
来源: https://www.2cto.com/kf/201802/717590.html