What's New In Git 1.8.5
blogs.atlassian.com
blogs.atlassian.com
Can't help but notice OP's blog platform replaces "--" (dash-dash) with "–" (U+2013, en dash), even in <span>s meant for code highlight. This prevents straightforward copy-paste of arguments like "--prune" to console ;-)
instead a lot of relatively minor things i don't really care about (i'm sure its useful) - also seeing 'something now implemented in C' instead of 'something now 30% faster (because implemented in C)' is slightly worrying because users don't care about implementation details unless you get something else very very wrong...
my issue with recursive merge is that 'works for 90% of linux kernel changes' or whatever it is is just not the same as 'works reliably'.
git fails to meet my minimum requirements for usable source control because of the extreme difficulties I seem to have with undoing a merge if i don't change settings ahead of time (i.e. there is a bug which is a bad choice of defaults). i give it a good go, i get help from the community, i exhaust documentation and google - it doesn't work for me. maybe i don't understand something - i don't want to understand it, i want it to 'just work' and 'be user friendly'.
git reset --hard HEAD~
That just kicks you back to the commit just prior to your current (merge) commit. Are you talking about trying to undo a merge further back in the commit history?if i merge two branches, push that to the remote and i wan't to undo it.
So actually reverting a merge in git isn't that painful. It's typically just git revert -m 1 sha_1_of_merge_commit
The problem is that if you then do more work on the branch and fix the problems that caused the merge to be reverted, redoing the merge doesn't work the way you expect; the commits that were previously merged don't get re-merged. So re-merging the branch consists of reverting the revert and then merging to get the new commits. Which is painful in-as-much as it requires you to know about the previous revert.
My favoured solution to this is to never merge, always rebase, which also has the property of giving a nice linear history that can actually be understood. However some people prefer a merge-based workflow (and if you happen to use github it is very difficult to enforce anything else, due to the Big Green Button), so it is a real problem.
This also gives you a chance to fix up any conflicts before merging, instead of possibly having to merge twice.
I agree with your "always rebase" method, the readable history is well worth it alone.
A good solution like GitHub Enterprise or Stash will allow you to use pull requests, so you can require that code gets reviewed by a third-party before merging.
In the case of Atlassian Stash, you can set branch permissions, which allow only certain users to commit/merge to that branch, and you can also require that a merge request be reviewed by specific individuals before the system allows it to be merged.
Preventing the merge problem in the first place is a much better approach than trying to fix it afterwards.
In a perfect world, all problems would be prevented. Unfortunately, we live in the real world, where being able to fix it afterwards is very important.
Say 'abc123' is the commit immediately before the merge commit. Run this:
git rebase -i abc123
In the editor window that appears, delete the commit(s) that you want to "pretend never happened". Exit the editor. Git then replays the commits from abc123 up to HEAD, except without the commits you deleted. Now your local branch is in a state that omits the premature merge commit. git reset --hard <previous commit's hash>
and afterward you may have to git push --force
...to overwrite the changes in the blessed/central/public/shared repo.i really don't mind conflicts. safety over rushing every time...
Is this referring to git 1.9? Are there any resources to learn what that will bring?
1: http://stackoverflow.com/questions/16308484/any-information-...
2:http://search.gmane.org/?query=%22what%27s+cooking+in+git.gi...
fwiw you've been able to type "head" for quite a while (forever?). TYPING IN ALL CAPS is a bit of a pain, I agree, but at least for me "head" is somewhere on the same level of typing-complexity as @, possibly easier.
$ git show head
fatal: ambiguous argument 'head': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ git show head --
fatal: bad revision 'head'
$ git version
git version 1.8.4.2EDIT: to expand, reference lookups are filysystem lookups:
01:42:24 (gh-pages) [bpowers@fina myproject]$ strace git show HEAD 2>&1 | grep HEAD
execve("/usr/bin/git", ["git", "show", "HEAD"], [/* 79 vars */]) = 0
lstat(".git/HEAD", {st_mode=S_IFREG|0664, st_size=25, ...}) = 0
EDIT2: formattinggit rebase @~4 looks like Perl :)
I only complain because in hg, "." is the equivalent to git's HEAD, and it's already difficult enough for git users to understand any system other than git after they spend time learning its idiosyncratic and inconsistent UI.
And it's not as if "git checkout HEAD" makes any sense either, this is a no-op, since you can't be on anything but HEAD.
They're only the same thing at a fundamental level, just like eventually all a computer is doing is moving bits around and all data is a bit stream. This ignores that hey are not treated as the same thing from the UI point of view. If they were, they would not require a lecture to understand how to recover a commit made on a detached HEAD, a lecture that git provides.
They are the same thing both in implementation and UI.
The various consequences of detached commits and what happens when you try to modify the working tree when there are uncommitted changes are both concepts that permeate all of git. Handling these things in a graceful manner does not somehow mean that checking out branches or commits are fundamentally different concepts.
If you want an example of muddled UI, git-checkout -b is an infinitely better example. Creating a branch is conceptually unrelated to checking out a branch; git-checkout just provides the -b flag for convenience because typically you want to check out the branch after creating it. It would likely make more sense to provide a --checkout flag of some sort with git-branch, as creating the branch is the primary operation and checking it out is just a secondary convenience. That is a decent complaint.
If this is the sort of thing honestly that bothers you, then just make a git-changebranch alias for git-checkout, pretend that git-checkout can't do branches even though it can do arbitrary commits, and move on with your life.
The only real difference here compared to Mercurial is that Mercurial doesn't issue a warning/lecture... In both cases you will have to know the changeset (or revision number in Mercurial) to get back to that anonomous branch (unless it's tip, but tip has its own issues). Git providing a warning for this is fair imho, as Git garbage collects anonomous branches. That, however, does not change the fact that checking out a random commit and a branch are the same thing in UI and implementation.
"git checkout HEAD" makes perfect sense in this case, cause you are checking out files from the commit pointed at by HEAD. Of course, checkout doesn't overwrite files in the working directory that are modified, unless you provide the -f option.
(4) is a convinience option and is more like "git branch <name> && git checkout <name>" Mercurial also does 'crazy stuff' like this. Like "hg pull --update" which is really just "hg pull && hg update".
I also don't understand what about "Detached HEAD" requires a lesson? Detached HEAD just means that the current HEAD doesn't isn't pointed at by a branch pointer. You have the same thing in Mercurial, it just doesn't warn about it. It's not really that big a deal in Mercurial either, as anonomous heads aren't in danger of being garbage collected.
git lectures you when you do this. That's the lesson.
There is no difference in "git checkout <changeset" and "hg update <changeset>". NONE. WHAT. SO. EVER. Except that Git gives you a warning that commits on this changeset results in an anonomous branch. And Git is filled with helpfull texts like this. Git status tells you how to revert files. Git rebase tells you how to abort.
I personally find this as something positive, as I don't have to lookup documentation whenever I want to do something.
There is, but you seem to be hellbent on ignoring it. And you're shouting.
The difference is that a commit made there is apparently "lost" in the git UI, because it's unreferenced. After 90 days, it's actually lost, or sooner if you do a casual "git gc". This is a problem that the user needs to understand and solve.
Commits in hg don't have to be referenced if you want to keep them. Hence committing at a past location in history doesn't require a lecture in hg. There is no problem to solve when you commit at an earlir commit on hg.
There isn't. There is a difference in the way git and mercurial handles anonomous branches (git removes them after a while), which i've already said a couple of times. There is however, no difference in how checkout and update works.
And I'm not shouting, that would make people at this office stare, and I don't like them staring. I instead wrote in all caps as I've repeated the fact that the two commands does the exact same thing, but you seem to be hellbent on ignoring that simple fact.
The commit is not lost in the git UI. You can either use "git reflog" or "git fsck --lost-found" to retrieve anonomous heads. If you want to keep them around, give them a name and you're done.
If you really want to view all branches, even anonomous ones, like you can with hg log, you can use "git log --graph --decorate $(git rev-list -g --all)"
> After 90 days, it's actually lost, or sooner if you do a casual "git gc".
If the reflog contains the last 90 days (doesn't it default to 14 days?), that commit will remain for 90 days, unless you delete the reflog. A "git gc" doesn't change this. As the commit is still in the reflog, "git gc" can't remove it, becouse the commits are referenced by the reflog. As a side-note, git push internally calls git gc (last I checked).
> There is no problem to solve when you commit at an earlir commit on hg.
Actually, this creates a new head which means you either have to use a named branch or --force the push. In git you don't have to make this choice. You do however have to tell git that you want the changes to stick around by adding a reference (branch or tag) to that anonomous branch within 14 days (before the commits exit the reflog).
If you're just testing something out, and find out you don't really need that code, you leave it unreferenced, and it will be removed eventually. I prefer this to manually using "hg strip" whenever storage gets low.
Besides, if you create a head with work you want to keep around, why wouldn't you reference it?
Comparing git to hg here is bad, as pointed out previously, '.' really does mean something more akin to what unix has always meant. I'd argue hg is more in the wrong here with reusing '.' as having other meanings for something that could semantically refer to a directory under version control.
Bitch about gits interface all you want, but not using '.' is between you and me a crap argument if you're going to invoke the "unix person" gods.
git checkout dir (lets assume cwd is in a git repo)
cd dir && git checkout .
And for completeness:
git checkout fileI don't buy the argument that something could be a path or a ref is bad in this case. It allows for both common cases simply. Want to update a single file/directory git checkout that file. Want to checkout a revision? Checkout the sha1hash.
Basically what I'm saying here, is reusing '.' is more of a problem for hg in that they're repurposing an already common idiom in unix.
If my arguments to why aren't convincing we'll have to disagree that this is a git "fault" or "inconsistent ui". I think of it as neither however.
Here, this is a funnier way to explain why "git checkout" is such a weird command:
Updating a file and updating a directory to me are effectively the same thing. The fact that git checkout can accept either a filename/directoryname, or a revision strikes me as no worse/better than the alternative in hg.
That is:
git checkout file/directory
git checkout revision
Is no better/worse than: hg revert file/directory
hg update -r revision (or wherever . is actually used, i'll admit I've never used it in mercurial)
In fact in many ways the git methodology maps closer to how english verbs are overloaded as well. That is, we're checking out some file/directory named whatever back to its last known good value, or we're checking out everything to a specific revision (I'll omit every option possible for brevity). Its rather easily parsed and explained to humans. The mercurial versions to be honest seem more pedantic than intuitive. I have to use both and vastly prefer the git way in this regard. But to each his own.The link is cute but I couldn't get past the first few paragraphs. It is trying a bit too hard to be funny/cute for my tastes. That said I looked at the listings of things that are messed up and sure I don't argue that git has an "intuitive" interface by any means in regards to listing tags/revisions. But this one point I don't see as its most glaring of issues. If its that big of an issue just do what I do and create a git alias in .gitconfig to call the arcane incantation of magick. Then it doesn't really matter how inconsistent it is.
Eh enough not working for me, tschuss!
The fact that you think of those as two separate operations is because you are used to systems that treat them as such.
git is already scary enough without stuff like
git show @~3^2^As for your scary example, if you don't like using "@" as an alias for HEAD, don't do it. <shrug>
I'll be glad to save another 1 character with 1.8.5.
Just because Mercurial does it, doesn't mean that it is thought out or makes sense.
Why is it a good analogy?
Directories are doubly linked trees^, each directory containing references to all child directories and a single parent directory, with some spacial implications (it makes sense to talk about directories being in or containing other directories). Commits make up singly linked DAGs, with each commit only having references to potentially many parent commits but no child commits, with strong temporal implications (it makes sense to talk about commits preceding or following other commits, with distant simultaneity frequently making an appearance). These two concepts really have very little overlap, other than both being graphs.
Even if we just decided that "HEAD"->"." anyway, we can't keep that up for long. What the hell would ".." become? "HEAD^" might seem like the obvious answer, but you would be left to figure out what the "directory equivalent" of "HEAD^2" is. "HEAD~2^2"? The Unix relative directory language is not expressive enough for git, even if you want to force the analogy for some reason.
Directories could be a good analogy for git's tree objects, but you operate on those through the high-level porcelain.
There are certainly problems with git's porcelain, and there are obvious improvements to be made, but this is not one of them.
^barring symbolic links, which we can ignore unless we want to open a whole 'Unix Haters Handbook'-esque can of worms...
> Why is it a good analogy?
Because it has associations "here" and "now" and "current". It doesn't fit all of the other meanings of "current directory", but it does fit the the "nowness" of it (just like git's trees don't have clorophyll or bark, that doesn't mean that calling them trees is a bad analogy).
Git trees are called trees because they are directed graphs without cycles. Directed graphs without cycles are called "trees" because they look mildly like them, but the name that you give them is of little consequence. That name does not really represent any sort of "UI".
roguelikes and unices grew up together, and there's a fair amount of intermingling of concepts and jargon.
...okay the reason is probably more like "'@' means 'you are here'", but I like this justification better because it's how it was explained to me at age ~7 when my dad was teaching me how to play nethack.
In hg, "@" is a special bookmark that gets checked out in new clones. There it means "this is where you probably want to be".
I remember Linus wanted to add a "generation" counter (empty commit=0, other commits=1+max(parent commits)) to speed up some merges; And I know I would love changes that would make big files properly supported (e.g. the way bup efficiently handles huge files inside a git repo).