9

I'm currently learning git, usually I'm a bit skeptic of VCS since I have a hard time getting used to them.

I deleted a branch called "experimental" with some tmp files, I saw the files removed in my working directory so I scratched my head and wondered if this is normal, can I bring it back in case I need it again, etc.

I found the SHA making the commit of the tmp files and recreated the branch with the provided sha and saw it again with all the files and their current content.

Everything I do in the working directory can be reverted once I commit it?

Might seem like a silly question to many people, but it kinda intrigues me so I want to know the limits

allenskd
  • 1,795
  • 2
  • 21
  • 33

4 Answers4

7

Almost every action can be reversed if you have committed the corresponding changes to your files. Even if you force-delete a branch or do a hard reset you can find the loose commit objects by using git reflog or git fsck.

However, loose objects are occasionally cleaned up by git gc, so you can't recover them after some time.

3lectrologos
  • 9,469
  • 4
  • 39
  • 46
  • You have to deliberately set a low `gc.pruneexpire` setting for `git gc` to immediately prune unreachable objects. Your last sentence implies that running `git gc` manually might be special. – CB Bailey Dec 30 '10 at 00:30
  • @Charles: I rephrased the last sentence. You are right, I didn't mean that a manual `git gc` immediately prunes loose objects. I just wanted to note that `git gc` runs automatically, but can also be run manually. – 3lectrologos Dec 30 '10 at 00:47
  • Does this answer apply to the local git repository only, or also to the remote when pushed (in the case of a centralized remote for instance) ? – nha Jul 19 '14 at 15:45
  • @nha The only major difference between "local" and "remote" (shared) repos I know of is that the latter are usually bare, i.e. include no working copy, but that should make no difference in terms of what is discussed above. – 3lectrologos Jul 19 '14 at 16:06
2

Everything I do in the working directory can be reverted once I commit it?

Yes you can. As an example, try git reflog. This will give you a list of commits made on the current branch. Pick one by its sha1 sum, then type git checkout 45db2a.... That checks out that commit. Be sure to git checkout HEAD or git checkout -b newbranch from that point if you want to make changes.

You can also use git to cherry pick these commits on top of your current HEAD (i.e. if they're done in a different branch, you can pull them in). This question discusses it far better than I can.

Community
  • 1
  • 1
  • After looking at the answers I'm kinda getting the hang of it, it's kinda confusing but not so much, difference (at least for me is) when pushing/pulling to the server. Now, I don't know if to ask in stackoverflow or here, but why "git rm" dry-run does not work? I had to delete my whole directory to reflect it in the private server. I want to keep my files and delete the ones over the server – allenskd Dec 30 '10 at 01:36
  • Ah, I see. You can force branches to be removed from a remote repository by doing this: `git push remotename :branchname` (strange syntax, `git push branchname` pushes it. The difference is just a `:`). I don't know if you can do this using individual commits, that's an interesting question. –  Dec 30 '10 at 01:43
2

The main point in any serious VCS is to keep the entire history of a project in a permanent and immutable way. So you can at anytime go to an arbitrary revision of your work.

There is a special behavior of git when it comes to its storage, in that it can remove objects if there are no references to it. References are:

  • each HEAD of a branch
  • tags (I'm not sure if an unreferenced annotated tag still acts as an active reference)
  • each commit which is referenced by another commit
  • the content of a branch reflog

This means that all commits, which are part of a branch are kept, also each object(=mostly commits) which are tagged. There is also a so called reflog on each branch(unless deactivated), where git keeps references to all objects you created in the last days. When an object is not referenced by any branch, tag or reflog, git gc removes it form the database. This is typical the case when you created a hacking branch, committed some stuff there, and removed this branch without merging it into another branch.

Rudi
  • 19,366
  • 3
  • 55
  • 77
1

git reset --hard can remove changes irreversibly

seriyPS
  • 6,817
  • 2
  • 25
  • 16
  • @3lectrologos hmm interesting... How i can Undo-hard reset? – seriyPS Dec 30 '10 at 00:26
  • 2
    I think that @3lectrologos is assuming the "once I commit" state. – CB Bailey Dec 30 '10 at 00:32
  • let's see, if i do my changes, but messed up, i could reverse all my files to the last commit using git reset? – allenskd Dec 30 '10 at 00:32
  • Of course I'm talking about a "once I commit" state (that's what `git reset` is all about). You can undo a hard reset by finding the pre-reset commit SHA using `git reflog` and then doing a new hard reset onto that. See http://stackoverflow.com/questions/5473/undoing-a-git-reset-hard-head1 – 3lectrologos Dec 30 '10 at 00:37
  • @allenskd, you can reset it again using `git reset --hard HEAD@{1 minute ago}` – J-16 SDiZ Dec 30 '10 at 00:42
  • 1
    @3lectrologos: In fairness using `git reset --hard` to throw away working tree changes is a very common use of `git reset` so starting from a clean state isn't all that `git reset` is about. – CB Bailey Dec 30 '10 at 00:47
  • 1
    @J-16 SDiZ: I'd prefer `git reset --hard HEAD@{1}`; at least it isn't time sensitive. – CB Bailey Dec 30 '10 at 00:48
  • 2
    @Charles: Yes, it is common. However, an answer like this is misleading, because it doesn't focus on the irreversibility of throwing away working tree changes (using `git checkout -- files`, `git reset` or `git clean`), but rather leaves the impression that `git reset --hard` in particular is an irreversible action. – 3lectrologos Dec 30 '10 at 00:55
  • @3lectrologos: I agree that this answer is misleading. If the statement in the answer correct in some way then it's certainly not in the way that the question was asked. – CB Bailey Dec 30 '10 at 00:59