Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Things about Git (matheuslima.com)
27 points by matheusml on May 25, 2014 | hide | past | favorite | 27 comments


> Last friday I lost a commit using git reset --HARD

You don't lose a commit just because you use git reset --hard. The author either doesn't know how git branches work and/or how to use reflog, or he means to say he lost the uncommitted content of his working tree.


git reset --hard

These days there's little reason to do reset --hard. `git reset --merge` is much safer and can be used almost anytime you would have otherwise done `--hard`.

e.g. if you want to force your branch to point at "foo", you can `git reset --merge foo` and it'll bail out if it detects that you have uncommitted edits that would have been lost by moving to "foo". If it can safely move the uncommitted edits there, it'll do it.


It was 'git reset --HARD <commit-id>', like a cherry pick, before pushing.


Even with --hard, the commit isn't lost. Commits are not immediately removed from the repository, only when git runs the garbage collection. Try it: create a test commit, make a note of its hash, reset to HEAD~1 and then reset again to that hash.

When you do this by mistake and you don't know the hash you can find it using git reflog, which logs everything that happens in the repository.

More detailed: http://gitready.com/intermediate/2009/02/09/reflog-your-safe...


If it was "before pushing" that means the commit has been made, and thus isn't lost (but accessible via the reflog.)


  git reflog
Might be your saviour here next time.


I'll update the post. This worked for me. Thanks a lot!


> If you want to check what it's difference between two branches, you can simply do: git diff branch1..branch2.

This won't give you the difference between two branches, it will give you the commits in the second branch which are not in the first one (technically it will give you the commits accessible from the second revspec which are not reachable from the first one, they need not be branches).

This means you won't see things in branch1 which have changed since the branches split.

If you want to see the differences between the two branches, you need to use <rev1>...<rev2> (three dots)

In set-theoretic notation, the first one is `a(branch2) \ a(branch1)` while the second one is `a(branch1) △ a(branch 2)` (where a is the ancestors-and-self function)

> Most people just use git status, but you can pass arguments to change the way status is shown. With git status -sb you have an output like this:

> ## master > M Gemfile > M Gemfile.lock > M app/controllers/home_controller.rb > M app/views/home/index.html.erb

This is mixing 2 changes and missing important information:

-s will provide what most people are looking for here, that is an SVN-like "short status" with no prose or suggestion text. Because of the index, Git has 2 status flags, the index state (difference between repository and index) and the second one is the working copy state (difference between working copy and index). The flags also feature specific states for merging situations.

-b adds branch information to the short status format, as `local[...remote]` (with the remote being absent if the local branch has no configured upstream).


Hi. You appear to be too smart for your own good. "git diff A..B" is synonymous with "git diff A B" (i.e. just compare the two points in the tree without regard to their history). "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" (i.e. ... does what you think .. does). The manpage is very clear about this.


#3 is no longer the default behavior since 2.0 was released.

http://blog.nicoschuele.com/posts/git-2-0-changes-push-defau...


> The 'matching' option is the default behavior in Git 1.x.

Is Git 1.9.2 (latest binary release for Windows) actually Git 2.x? By definition, shouldn't 1.9 do matching rather than simple?


Downvoter, please comment on what you think I did wrong here? You clearly have been here long enough to get downvoting privileges but I guess you failed to learn proper etiquette? Maybe they ought to consider raising the bar to something like 1000 points instead of 500?


Ah yeah, my phrasing was poor on that. 2.0 has yet to see a stable release, but they started warning about the default setting changing a while back.


Thanks a lot. Updated!


You may want to leave it in. As another user mentioned, the official stable release is still 1.9. It does warn you that the default will change in 2.0, and prompts you to decide whether or not you want to keep "matching" as the default, but the version that most people will be working on won't have "simple" set as default yet.


Related, I'm sure many people here know this, but it's super useful for those that don't. To undo any uncommitted work and go back to the original state of the branch use: 'git checkout .'


I like doing a 'git stash' or 'git stash save deleteme' instead. That way if I realize a moment later that I needed anything, it's still available (if I haven't done a 'git stash drop' yet).


Also useful:

    git checkout -
to switch to the previous branch. Similarily,

    git merge -
to merge the previous branch into the current branch.


Since it looks like the author is idling in this thread:

I'm a enthusiastic git user, and I've ranted about a few git topics here: http://gitdoctor.com/

I also use the @gitdoctor twitter handle for helping people out in those moments of "oh shit, what is happening?!" with git :-)


For people coming from TFS who might think stash is similar to shelve... stash is local. It does not go to your remote (origin?) unless you do some special gymnastics. I don't know if it is even officially supported to push a stash to remotes.


> I don't know if it is even officially supported to push a stash to remotes.

I usually just create a temporary branch that I push upstream if I want to save my 'stash'. Is there a use case I'm not thinking of where pushing a stash upstream is useful?


The only use casei can think of is not knowing how easy branching and merging is with git. Or someone coming from svn thinking branches take up a lot of disk space and time. Stashes are meant to be local.

Its pretty easy to turn one into a branch too if you feel you should make a stash available over the net.


Just something good to know if coming from tfs side of things :)


This post was mostly misleading and unnecessary.


Even if that's true, you're talking like a dick.


> Last friday I lost a commit using git reset --HARD (shit happens), so I decided it was time to study

Mercurial?!

> git again

Aw.

It may be interesting to compare the safety nets that Git and Mercurial provides. Mercurial tries to steer you away from rewriting history, but it does supply a complete set of tools for doing it - it has rebase, strip, commit --amend and so on. The difference is in what happens to deleted history.

In Git, as i understand it, history is defined by the branch pointers and the commits reachable from those. Deleting history simply means fiddling the branch pointers; the underlying commits are still there, completely unchanged. But now you can only find them via the reflog (unless you wrote their hashes down or something). They will stay there until the next garbage collection cycle. I don't know what determines when garbage collection occurs, so that might be ages, or it might not be long.

In Mercurial, history is defined by the commit graph. If something is in the graph, it's in history. That means that to delete something from history, you need to actually remove it from the graph. Commits which are removed are written as bundle files to the .strip-backup directory inside the repository's .hg directory. These are compressed binary files, so they're not much fun to look at directly, and i'm not aware of any way to display their contents, but Mercurial can import them, so restoring the changes. These files are never deleted automatically.

Really, Git's safety net is more tractable - once you have identified a deleted commit, you can work with it in the same way as any other commit. Mercurial's safety net is purely cold storage. I believe this reflects the tools' different opinions on rewriting history: in Git, it's normal, so you'll need the safety net a lot, whereas in Mercurial, it's not normal, so you will only need it if you have been bad, and you should feel bad.

Fortunately, something that is slowly arriving in Mercurial is the concept of changeset evolution:

http://mercurial.selenic.com/wiki/ChangesetEvolution

Which basically keeps deleted commits in the tree, like Git, but marks them as deleted. Moreover, when you do things like amend or rebase, it marks commits as having been replaced by other commits. Those marks are in the committed metadata, and are propagated between repositories, which means it becomes possible to do things like safely rebase public commits, merge different attempts at rebasing some commits, and more besides. If changeset evolution works as well as is hoped, it will provide all the advantages of history mutation without any of the drawbacks, which will be super sweet.


Speaking of Evolve, I would like to promote my own talk + demo about it:

http://www.youtube.com/watch?v=4OlDm3akbqg




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: