39

I just added additional remote A to my repo B and then run git fetch A. How can I undo the fetch? If I just remove remote A: git remote remove A1 would it undo fetch?

UPDATE:

$ git remote add A path/to/A
$ git fetch A

The above are commands I run so in result I got all branches fetched to my repo B however I just need one specific branch from repo A and I need it to go in specific folder on repo B but that is another story Merge code between two dfferent git repositories.

Mark Fisher
  • 965
  • 1
  • 11
  • 30
Sergino
  • 10,128
  • 30
  • 98
  • 159
  • 2
    Why do you want to undo the fetch? – mipadi Feb 24 '16 at 02:01
  • also, if in doubt, you can try it. removing a remote is not going to break anything. – njzk2 Feb 24 '16 at 02:03
  • @mipadi Just want to cleanup whatever being brought to my repo – Sergino Feb 24 '16 at 02:04
  • for my understanding fetch is bringing files to my repo `.git` so why would I need them sitting there if I do not want to merge – Sergino Feb 24 '16 at 02:08
  • @sreginogemoh, to keep you local repo updated. Git is a DVCS. It relies on everyone having the latest copy of the repo. That way backups are not necessary as everyone who has cloned the repo has a backup. – TheGeorgeous Feb 24 '16 at 02:56
  • @TheGeorgeous But in my that case it is custom remote where I do not to pool all the branches from. However fetch brought all branches from `repo A` but I just need one single branch for it. So fetch just brought stuff that I do not need at all and never will. – Sergino Feb 24 '16 at 04:15
  • If you just want to remove particular remote branches, use `git branch -r -d`. You will still retain the objects for the usual retention period (default 14 days). You will probably want to tweak your configuration though, so that future fetches from the same remote pick up only the specific desired branches. – torek Feb 24 '16 at 22:06
  • this question is very important when you accidentally fetch all the feature branches from all your companies developers over the last 5 years. I only want branches I need in my local repo – bodovix Jan 07 '21 at 15:20
  • @bodovix I'm curious what the use case would be for keeping merged feature branches around. (I can think of some, but they're quite contrived.) – TTT Jun 03 '21 at 19:33
  • @TTT suppose it depends what/where you work but Audits would be one, our feature branches get matched up with the stories so purging them after X months would make us loose that level of trackability. Idk, I like keeping branches I've done around locally, but it used to annoy me when I accidently fetched 100s of others. I've since discovered the wonders of Grep though so now its super easy to filter them down and this doesn't bother me so much: git branch -a | grep "myFilter" – bodovix Jun 08 '21 at 08:42
  • 1
    @bodovix I guess there are many ways to skin that cat. In our case, between merge commits with commit messages that reference the story number, or even from the history stored within the PR tool, we could always re-create any feature branch we wanted without having to save any of them. But if you don't use merge commits or a PR tool with history then you would need another way, and keeping the branches in the repo is certainly one way. – TTT Jun 08 '21 at 14:33
  • 1
    @TTT well, that's why I assumed we keep ours around for ages, but who knows. It could just be because that's how its always been done. I might enquire further ;) - but regardless greps pretty much voided this issue for me – bodovix Jun 08 '21 at 15:11

5 Answers5

44

You can undo all fetches from remote A simply by removing this remote:

git remote remove A

Now just add it again and fetch only single branch:

git remote add A <path/to/repository>
git fetch A <name of branch>
qzb
  • 8,163
  • 3
  • 21
  • 27
20

It is difficult1 to "undo" a git fetch, but there is never2 any reason to need to undo a git fetch.

Remember, what git fetch does is call up the remote, get a list of branch-name to SHA-1 mappings, bring over commits and other objects you need in order to store those in your repository, and then update your remote-tracking branches so that they point to the remote's current (as of the time you just now phoned it up) branch tips. This has no effect on any of your work-tree files, and if you run git fetch again tomorrow, any work done today can be skipped tomorrow. If you do manage to undo the fetch, the one run tomorrow will have to re-do the work done today, so this is a net loss: you just spent some effort so that your git will have to bring more code over the network tomorrow.

That said, time for footnotes. :-)


1It's not that difficult if you have remote reflogs (which you probably do): just use the remote reflogs to find remote-tracking branches updated in the most recent fetch—this same information may also still be available in the FETCH_HEAD file—and then use git update-ref to point those references back to their previous reflog entries. But this will still leave the fetched objects in your repository, so to really clear them out, you must then also delete the intermediate reflog entries, and then run git gc --prune=now, which requires a lot of care and will discard all unreferenced objects, not just ones brought over by the most recent fetch.

2I think one could argue that "running low on disk space" might be a reason to do this, especially if a large object was accidentally pushed to the remote and will be removed from the remote by the next fetch. Working in a file system that is out of space is tricky in general, though, and I'm not sure I would want to do much here other than move the entire repository elsewhere (somewhere without the disk space issues).

torek
  • 448,244
  • 59
  • 642
  • 775
  • A fellow contributor could have committed changes that cause problems. The offending commits can be removed temporarily by resetting the HEAD but the log pointer to "master" will not reappear. That can make it more challenging to rebase feature branches and has been a reason why I would have liked to undo fetch in the past. – Felix Lechner Jul 04 '19 at 12:56
  • @FelixLechner: those commits will be reachable exclusively by *remote-tracking* names, such as `origin/master`, or tag names. They will only become reachable by your own branch names if you take some action—such as running `git merge` or `git rebase`—to *change* your own branch names. Your own branches are always unaffected by `git fetch`. When you want to rebase or merge, you can do it by commit hash ID instead of branch name. – torek Jul 04 '19 at 17:48
  • I have a *very* good reason to undo a `git fetch`. I have fetched a few months of commits of the Chromium repository and would like to get my 100GB of disk space back. I have fetched with `git fetch --depth=100000` in order to only get the last few months, now I would like to delete it all and only fetch the last 100 commits or so. – Jespertheend Jun 16 '21 at 21:52
  • @Jespertheend: you can do a `git fetch --depth=100` to shallow things out some more, but I'm not sure that `git gc` will clean up the mess here. But I'll note that 100 GB is [about US$5](https://www.blankmediaprinting.com/blog-article/cost-gigabyte-popular-data-storage-types-infographic). (I know, it's not really that simple. I need to upgrade my own system and I feel the same pain :-) ) – torek Jun 17 '21 at 14:23
  • @torek I ended up just removing the whole repository and fetching it again. Fortunately setting up the build pipeline wasn't too complicated. Purchasing an extra hard drive isn't the issue though. I have several hard drives lying around that I could use. But having external devices connected to a laptop isn't ideal and MacBooks can't easily be upgraded. – Jespertheend Jun 17 '21 at 18:20
  • Another reason to want to undo a fetch is if you hit a Git bug in a real life situation during `git fetch` and want to reproduce it ;) – philb Jun 29 '21 at 12:31
  • @philb: if you're at that level (debugging Git) you should know how refs and refspecs work :-) – torek Jun 29 '21 at 21:10
  • I do know how refs and refspecs work! :) However, when I hit a Git bug during a `git fetch`, I would really, really, like to be able to go back to the repo state before the fetch, take a backup of my repo to be able to reproduce the bug, redo the fetch and get on with my day. To this day I have not yet succeeded. I know how I can roll back the refs and the reflog, but it's deleting the fetched objects which is tricky (especially as they often are in a pack...) – philb Apr 22 '22 at 19:03
  • @philb: well, yes, but that's more an issue of the packfiles than the refs at that point. What you want is `zfs snapshot` or equivalent (equivalent = "copy .git dir", usually). Unfortunately you only realize you want that right *after* it's too late... – torek Apr 22 '22 at 20:05
  • I think there are good reasons to undo `git fetch` when the remote has 10s of thousands of branches. It slows git branch autocomplete down to take 5+ seconds rather than being instantaneous. – Ozymandias Mar 06 '23 at 20:05
9

I really liked answer from torek, but it doesn't provide you commands to "update reflogs", which is exactly what I was looking for. I found this in other answer reverse a git fetch, so I just leave it here to simplify searching for others.


Let's assume that you have your origin remote and your local develop branch is based on master, but your local master is behind origin/master (but you don't see it yet, because you haven't fetched origin yet).

So performing git fetch will add new commits from origin/master and tags to your local repo. In some cases you don't want to see those new commits at all and they will reduce readability of your history.

Having said that, you can "undo" git fetch by doing:

git update-ref refs/remotes/origin/master refs/remotes/origin/master@{1}

All this does is changes the origin/master pointer to the previous state. Maybe you'll have to play with {n} a bit to get the exact state, but in general it may help.

The Godfather
  • 4,235
  • 4
  • 39
  • 61
  • well, update-ref is half of the story in my case.. i want to literally bring local repository to the state it was before fetch , to make sure next 'git fetch' will go and download file(s) from remote repository.. the problem i faced is strange error 'error: inflate: data stream error (unknown compression method) fatal: failed to read object' , and also, there's a warning message that my git is older than one used on remote.. so i wanna prove or disprove whether it is simply repository corruption , or in fact, there are new compression method, that my local git can't handle. – Igor Stasenko Apr 22 '20 at 19:27
5

Very Simple Solution:

git reset --keep HEAD@{1}

Or Second Solution:

git reset --hard master@{"10 minutes ago"}
yash sanghavi
  • 368
  • 3
  • 5
4

You can delete whatever branches you accidentally fetched that you don't want to keep with the following command:

git update-ref -d refs/remotes/YOUR_REMOTE_NAME/BRANCH_NAME_TO_DELETE

To prevent them from getting fetched again, set your git remote to only fetch specified branches: git remote set-branches YOUR_REMOTE_NAME desired_branch1 [desired_branch2, desired_branch3, etc], e.g. git remote set-branches origin master.

The default behaviour of set-branches is to always replace the list. If you want to append, use the --add option: git remote set-branches --add origin another_branch

Olimon F.
  • 141
  • 3
  • This is the real answer to the question IMO. The various debates about whether one should really do this are valid, but don't answer the question. – bryant Jul 28 '22 at 20:58