8 ms·
The real problem here is: ... "and I was getting ready to commit a series of important changes" ... Before doing so, I want to merge in the recent changes from
by gst 15y ago
The real problem here is:
... "and I was getting ready to commit a series of important changes" ... Before doing so, I want to merge in the recent changes from the remote master, so I do the familiar git pull. ... "maybe I’m going slightly crazy after 3 days straight hacking" ...
Do I interpret this correctly as that the author has not commited any changes for 3 days?
With SVN there may be an excuse for this, but with Git the right way is to commit as often as possible, and then squash your commits before pushing them. With such a workflow the problem would have been a non-problem - just use git reflog and checkout your previous version.
Of course you wouldn't use a git pull then, but just rebase your local commits on top of master.
Learn how to use your tools, instead of complaining about them!
- jvm 15y agoThose were my precise thoughts. This is exactly the kind of problem that is easy to avoid in a distributed VCS and hard to avoid in a centralized VCS.
- skew 15y agoThe kind of problem where merging a commit silently overwrites a completely unrelated file with an older versions? It was a clear case of git violating a promise of safety made in the documentation, and a nice study of tracking down the bug.
- gcv 15y agoI agree that the author should've been committing far more regularly than he apparently does. In addition, "git pull" is a bad idea (you never know what nastiness someone else might have committed — "git fetch" + "git merge" is a far saner way to stay up-to-date). That said, hats off to the author for tracking down the problem. Regardless of workflow flaws, the behavior he observed is a bug, and I'm glad it's fixed.
- jbellis 15y agoCan you elaborate? A lot of beginner level material explains "pull" as a combination of "fetch" + "merge." What makes the latter saner?
- fphilipe 15y agoIt rewinds your work, fast forwards to the fetched branch and applies your work on top of it. It doesn't create a merge commit, which can pollute your tree unnecessarily.
- davvid 15y agoI believe you're describing "git rebase". e.g. git fetch git rebase origin/master instead of: git pull which you can also do with: git pull --rebase But really, the preferred way is to use topic branches. So if you're on branch "foo", this is how you integrate into master. git checkout master # because it always matches upstream git pull # this will always fast-forward git merge foo git push That does create a merge commit but it does it in the right direction (master 1st parent, topic branch 2nd). You get to see the parallel development which is good to preserve in the history. Otherwise, rebasing is nice because it keeps the history linear.
- fphilipe 15y agoYeah, you're right. I must have misread the question. Didn't know about `git pull --rebase`. Thanks for that.
- click170 15y agoBy doing a fetch first, and a merge in a separate operation, you're at least presenting yourself with an opportunity to check the code that you are merging. With `git pull`, it is all done in one operation. Of course, if you've already reviewed the code or are pulling from your own remote repository then `git pull` is likely fine.
- gcv 15y ago
- bennoleslie 15y agoJust to point out that fetch + merge would have caused the same problem. In this case it was a small team, with advance knowledge of what the commit was, so no need to inspect. But, in any case doing the fetch would have shown that the file was not modified in the fetched tree, and it would have gone ahead and overwritten my changes (without even listing in the merge log that the file was changed). FWIW, I agree that fetch + (merge | rebase) is in general the best way to go, but I think there is a case when you a pulling in a simple fix from head where doing a pull is legitimate. After all the documentation says this is a safe operation: "If any of the remote changes overlap with local uncommitted changes, the merge will be automatically cancelled and the work tree untouched" (from git pull --help). If this isn't meant to be considered a safe operation git pull should abort if there are any changes to the working directory.
- SomeCallMeTim 15y ago"Safe" or otherwise, it's (IMO) never a good idea to merge uncommitted files. You're losing history that way: If the merge doesn't actually work, then you've got a screwed up file and no way to roll it back. It's one of the great strengths of git that you can commit files even if someone else has changed them. It's a bad idea to merge when you have anything significant checked out (I'll leave temporary debugging changes checked out, or very small changes, but that's it). Heck, it's a good idea to check in every few hours, to track changes your making.
- gregors 15y agoAgree 100% I've seen this same type of issue occur in mercurial when people were doing what I call "all or nothing merging". You should not be merging unless you can get to the precise pre-merge state.
- Vitaly 15y agothe real "mistake" here was not doing 'pull' it was doing 'pull' while having uncommitted changes in the working directory. I'd commit or stash before the pull/
- Roboprog 15y agoFor the life of me, I could not figure out why he would not save his changes before pulling stuff down on top of them. Some people still go days without saving, which is foolish in my opinion. Change a function (or similar unit), and save. Rule for dummies: save before leaving for the day (but that's not granular enough).
- EdiX 15y ago> For the life of me, I could not figure out why he would not save his changes before pulling stuff down on top of them. He appears to be using git with the svn workflow (svn update; svn commit).
- Roboprog 15y agoOK, thanks for the reminder. Even back when I did use SVN regularly at work, we usually worked on feature branches, and seldom ran into collisions requiring that process. I'd forgotten that SVN will force an updage (merge) before commit in some cases. It had not occurred to me that somebody would internalize that as SOP.
- barrkel 15y agoThat's not my svn workflow; it's svn diff to a patch file, svn revert, svn update, then patch from the patch file (and resolve conflicts if necessary with a decent third-party tool), then finally svn commit. I run svn diff multiple times a day. I frequently have many different patches related to different functional areas and bug fixes. Effectively I work with local branches implemented on top of svn. I have a whole suit of scripts that automate this. Seemed like the only workable way to use svn in a disconnected fashion to me.
- masklinn 15y ago> Effectively I work with local branches implemented on top of svn. I have a whole suit of scripts that automate this. Seemed like the only workable way to use svn in a disconnected fashion to me. Why don't you just use git-svn or hgsubversion and stop doing that informally? Or at the very list use something like `quilt`, so that your changes are represented as a stack of patches on your svn "upstream"
- regularfry 15y agoHow is it relevant how long it was since he last committed? It sounds from the description like this could happen if he'd committed five minutes before. It's still not cool to clobber work like that.
- EdiX 15y agoNormally in git you never pull on a dirty working dir, you either stash or commit your work and then pull. That's why this bug is unlikely to trigger normally.
- bobwaycott 15y agoExactly what I was thinking. I'd have done: git fetch git stash git pull --rebase branch-name git stash apply All this cp business struck me as a bit of not understanding how to properly work with git. I've never had my work clobbered by following the strategy above. But I also don't go very long between commits on my working branch.
- mainguy 15y agoYour workflow is a little overcomplicated.. I think the following will produce identical results: git pull --rebase branch-name
- jrockway 15y agoHe is using "git stash" to create a commit object for his uncommitted changes, giving him more documentation in the event that Something Goes Wrong. Git will never throw away your data, but you might get into a weird mental state and type a command that throws away your data. By creating a commit object, you can always get back to that state, and you have a little one-line note-to-self that helps you not get into a weird mental state. I personally do a "real" commit before rebase, but "git stash" is really the exact same thing. I guess "git stash pop" is less scary than "git rebase HEAD^". Either way, you can always undo that operation via the reflog.
- 15y ago
- nahname 15y agoNot just that, I believe he didn't commit anything and was using git pull to update his workspace.
- grammaton 15y agoMore to the point, shouldn't it be a git pull --rebase?
- theshadow 15y agoOfcourse it's the victim's fault! The grandma who's been writing a letter on word loses it after an unexpected blue screen of death, ofcourse it's her fault. A guy gets stabbed at 2am at a bus stop; clearly the guy's at fault. Shoulda known better than hanging out in that part of the town at that hour. A car blows up when a woman fills it up with regular gas instead of premium; you had it coming lady, learn to use your car rather than now sitting in the hospital and complaining about it. We are cool like that, we blame the user when out favorite tool screws the pooch big time.
- sunchild 15y agoGit doesn't kill code, people kill code.
- Radim 15y agoNo, you interpret it incorrectly. From the article: git has just gone and destroyed the last 5 or 6 hours worht of work. Not happy!
- InclinedPlane 15y agoDefinitely. However, this highlights a problem with git, it should naturally guide you to best practices. Unfortunately, with git it's quite easy to fall into a natural and comfortable seeming pattern of use that has some very negative downsides, such as the author of the article experienced.
- bennoleslie 15y agoExactly, in fact it normally does. git pull is actually really useful for enforcing this most of the time. If you inadvertently do a 'git pull' before doing a commit, and you have any overlapping changes, then git aborts the merge. This is why 'git pull' is generally a safe operation.
- bennoleslie 15y agoNo, you don't interpret correctly. It was not 3 days of uncommitted changes, it was committing some changes after hacking for three days. Completely different thing. The 3 days was relevant because I was tired and my first assumption is that I had done something wrong. It turns out there was a nasty bug. Also, I don't think my workflow is that broken: "Linus often performs patch applications and merges in a dirty work tree with a clean index." [1] http://gitster.livejournal.com/29060.html http://gitster.livejournal.com/29060.html If I am pulling down some unrelated changes, it is not unreasonable to do that. That is one of the features that git provides. I know perfectly well how to use git, in a number of different work flows, and I use whichever is most appropriate for the given project at the given time. Also, I don't think my post was complaining. It wasn't 'OMG git is the worst, I'm never using it again', it was an analysis of a particular nasty corner case in git.
- jamieb 15y agoYou referenced that article to claim that Linus does what you did. But that article is quite clear that Linus does not do what you do: He either reverts, commits or stashes first. Had you done that you would not have had your problem. Its one thing to fuck up and get panned on HN. Its another to go looking for justification that you are right. Its yet another to select a single quote from an article to justify your position when the entirety of the article refutes your claim. You did a great public service by calling attention to this problem (the problem being not using git properly - nobody is going to hold that against you). Don't ruin it now by getting all defensive.
- bennoleslie 15y agoSorry, that did come across as a bit defensive. However, I think if you read the whole article carefully it explains that after doing a git pull, and git refusing to merge because of outstanding changes you then have a chance to either 'revert, commit, or stash'. That is exactly the behaviour I expect from git, and exactly what broke down in this case.
- jrockway 15y agoCame here to post this. The key thing to know about git is to always, always, always commit your changes before doing anything that affects history. This is not for data loss reasons, it's for being able to document what is happening; when you have a bunch of unsaved work, you don't know what's there and git doesn't know what's there. Therefore, it's very easy to get yourself into a state where you don't "care" about your working copy, and that's when you can do something where you lose work. If you commit before you do any merging or pulling every single operation that you perform afterwards can be reverted cleanly. And, you'll have a human readable note that documents what you were thinking at the time. If you don't put your work into git, it can't track it for you. You can always uncommit if you don't like what you committed. In fact, you should consider your local history to be a work in progress; just like you're editing your source code to keep it clean, you should be editing your history to keep it clean. Git never deletes history, so even if you edit it, you can always get back to where you were. What you call "master" may have changed, but what was master before your rebase still exists, in its entirety, inside of git. (It's simply called HEAD@{0} instead of master. See "git reflog".)
- __david__ 15y agoYou are correct, though I'd also point out "git stash" which does a quick no-fuss commit and is meant for situations just like this. "git stash" "git pull" "git stash pop" may not be exactly what you said but it should be enough to prevent what happened to this guy and I'd even guess it is what most new git users expect to happen when you do a plain "git pull".
- deleted 15y ago[deleted]