From: Greg A. Woods <hidden> Date: 2016-06-15 22:47:47
I'm trying to learn to use Git to manage local changes. I'm very new to
Git (hi all!), but not new at all to version tracking tools in general.
Hope I've found the right list on which to ask potentially naive
questions! I've been doing _lots_ of reading about Git, but I can't
seem to find anything about the problems I relate below.
One task I'm working on is to try to find the best way to merge changes
made from one branch to another, eg. to propagate local fixes from one
release to another.
However in at least one simple case "git merge" merges too much.
I have something like this started from a remote-cloned repository where
BL1.2 is a branch from the remote master HEAD, which happens to
correspond to a tag "TR1.2", the release-1.2 tag, and I've made three
local commits to my local BL1.2 branch: A, B, and C:
BL1.2 - A - B - C <- BL1.2 HEAD
/
master 1 - 2 - TR1.1 - 3 - 4 - 5 - TR1.2 <- master HEAD
(there are no "release" branches in this project, just tags on the
master branch to represent release points -- is there any way to get
"git log" to show which tags are associated with a given commit and/or
branch? The real project is freedesktop.org's xinit repo, but the real
tree is too messy to diagram here -- hopefully I've extracted the
essence of the problem correctly)
I now want to create a branch "BL1.1" and merge commits A, B, and C to it
in order to back-port my local fixes to the TR1.1 release. "TR1.1" is
simply a tag on the origin/master trunk.
I do the following:
git checkout -b BL1.1 TR1.1
git merge BL1.2
However this seems to merge all of 3, 4, and 5, as well as A, B, and C.
I think I can (barely) understand why it's doing what it's doing, but
that's not what I want it to do. However it looks like Git doesn't have
the same idea of a branch "base" point as I think I do.
Running "git log TR1.2..BL1.2" does show me exactly the changes I wish
to propagate, but "git merge TR1.2..BL1.2" says "not something we can
merge". Sigh.
How can I get it to merge just the changes from the "base" of the BL1.2
branch to its head?
Is using either git-cherry-pick or "git log -p | git-am", the only way
to do this? Which way best preserves Git's ability to realize if a
change has already been included on the target branch, if any?
Is this the kind of "problem" that drove the creators of Stacked-Git to
invent their tools?
Is there any way to get "git log --graph" (and/or gitk) to show me all
the branch heads, not just the current/specified one?
--
Greg A. Woods
+1 416 218-0098 VE3TCP RoboHack [off-list ref]
Planix, Inc. [off-list ref] Secrets of the Weird [off-list ref]
From: Jeff King <hidden> Date: 2016-06-15 22:47:47
On Sat, Nov 28, 2009 at 10:21:25PM -0500, Greg A. Woods wrote:
Hope I've found the right list on which to ask potentially naive
questions! I've been doing _lots_ of reading about Git, but I can't
seem to find anything about the problems I relate below.
Yep, you're in the right place.
master branch to represent release points -- is there any way to get
"git log" to show which tags are associated with a given commit and/or
Try "git log --decorate".
BL1.2 - A - B - C <- BL1.2 HEAD
/
master 1 - 2 - TR1.1 - 3 - 4 - 5 - TR1.2 <- master HEAD
[...]
git checkout -b BL1.1 TR1.1
git merge BL1.2
However this seems to merge all of 3, 4, and 5, as well as A, B, and C.
I think I can (barely) understand why it's doing what it's doing, but
that's not what I want it to do. However it looks like Git doesn't have
the same idea of a branch "base" point as I think I do.
Yes. Git doesn't really view history as branches in the way you are
thinking. History is simply a directed graph, and when you merge two
nodes in the graph, it takes into account _everything_ that happened
to reach those two points since the last time they diverged (which in
your case is simply TR1.1, as BL1.2 is a strict superset).
There is no way in the history graph to represent "we have these
commits, but not this subsequence". You have to create new commits A',
B', and C' which introduce more or less the same changes as their
counterparts (and they may even be _exactly_ the same except for the
parentage, but then again, they may not if the changes they make do not
apply in the same way on top of TR1.1).
Running "git log TR1.2..BL1.2" does show me exactly the changes I wish
to propagate, but "git merge TR1.2..BL1.2" says "not something we can
merge". Sigh.
How can I get it to merge just the changes from the "base" of the BL1.2
branch to its head?
Is using either git-cherry-pick or "git log -p | git-am", the only way
to do this? Which way best preserves Git's ability to realize if a
change has already been included on the target branch, if any?
Yes, you must cherry-pick or use rebase (which is a more featureful
version of the pipeline you mentioned). Either way will produce an
equivalent set of commits (cherry-pick is useful when you are picking a
couple of commits; rebase is useful for rewriting a whole stretch of
history. It sounds like you want to do the latter).
The resulting commits will have different commit ids, but git generally
does a good job at merging such things, because it looks only at the
result state and not the intermediate commits. If both sides have made
an equivalent change, then there is no conflict.
Is there any way to get "git log --graph" (and/or gitk) to show me all
the branch heads, not just the current/specified one?
Try "--all" with either gitk or "git log". Or if you want a subset of
heads, just name them.
Hope that helps,
-Peff
From: Greg A. Woods <hidden> Date: 2016-06-15 22:47:48
Thank you very much for confirming my understanding of why "git merge"
was merging more changes than I had desired it to merge.
The way "git merge" works does concern me somewhat though as I try to
figure out how I might use "topic" branches to develop local features
and then merge them onto each supported release branch. Some guides
I've read suggest this methodology, but I'm sure how well this will
work, even when the remote project uses release branches to manage
official releases. Perhaps I really should look at StGit, but I'm not
sure about it either.
At Sun, 29 Nov 2009 00:14:27 -0500, Jeff King [off-list ref] wrote:
Subject: Re: "git merge" merges too much!
On Sat, Nov 28, 2009 at 10:21:25PM -0500, Greg A. Woods wrote:
quoted
master branch to represent release points -- is there any way to get
"git log" to show which tags are associated with a given commit and/or
Try "git log --decorate".
Excellent! That's exactly what I was looking for.
(From a first pass through the documentation I would never have guessed
that "tags" were also a form of "refs". All these different names for
things in the Git vs. many other VCS's, like "ref names" _really_
confusing to anyone like me with too much experience using those other
revision control systems. Part of the problem is that Git documentation
seems to be two-or-more minded about several of its concepts and
features. Even the gitglossary(7) is somewhat inconsistent on how it
uses "ref" and "refs". Perhaps all that's needed is some firm editing
and clean-up of the manuals and documentation by a good strong technical
editor.)
Yes, you must cherry-pick or use rebase (which is a more featureful
version of the pipeline you mentioned).
"git rebase" will not work for me unless it grows a "copy" option ,
i.e. one which does not delete the original branch (i.e. avoids the
"reset" phase of its operation). This option would likely only make
sense when used with the "--onto" option, I would guess.
"git rebase -i" would certainly give me all the control I could possibly
want when copying changes from branch to branch.
It likely wouldn't make sense to base this new "copy" feature directly
on "git rebase" though, especially in light of all the warnings about
how "git rebase" isn't friendly when applied to already published
branches. I think in theory this "copy" feature won't cause problems
for already-published branches.
Perhaps it should be a whole new top-level command such as "git copy",
but then it's so much like "git merge" I'm not sure.... Ideally if "git
merge" could be taught how to work with just the changes from the base
of a branch then it would do what I'm looking for directly.
The resulting commits will have different commit ids, but git generally
does a good job at merging such things, because it looks only at the
result state and not the intermediate commits. If both sides have made
an equivalent change, then there is no conflict.
quoted
Is there any way to get "git log --graph" (and/or gitk) to show me all
the branch heads, not just the current/specified one?
Try "--all" with either gitk or "git log". Or if you want a subset of
heads, just name them.
Awsome! Those options provide just what I wanted to see!
(git-log(1) is worse than ls(1) for having too many options, but worst
of all in the release I'm still using it doesn't respond sensibly nor
consistently with other commands when given the "-?" option.)
--
Greg A. Woods
+1 416 218-0098 VE3TCP RoboHack [off-list ref]
Planix, Inc. [off-list ref] Secrets of the Weird [off-list ref]
On Mon, Nov 30, 2009 at 01:12:31PM -0500, Greg A. Woods wrote:
The way "git merge" works does concern me somewhat though as I try to
figure out how I might use "topic" branches to develop local features
and then merge them onto each supported release branch.
The basic idea of using topic branches is development is done on
separate branches are merged to the release branch only when they are
ready to be released. These branches are based on the oldest branch in
what they may be included. It means that fixes are normally based on the
stable branch and new feature are based on the master branch, i.e. the
branch that contains changes for the next new feature release. Not all
branches got merged immediately into master. For instance, the git
project has 'pu' (proposed updates) and 'next' branches. Only when a new
feature proved itself to be useful and reliable, it is "graduated" to
the master branch. Thus the master branch is rather stable and it is
released on regular intervals (no need for a long stabilization period).
The key difference comparing to what you may got used is that branches
are normally based on the oldest branch in what this feature may be
included. Thus normally changes are not backported to old branches,
because you can merge them directly.
quoted
Yes, you must cherry-pick or use rebase (which is a more featureful
version of the pipeline you mentioned).
"git rebase" will not work for me unless it grows a "copy" option ,
i.e. one which does not delete the original branch (i.e. avoids the
"reset" phase of its operation).
There is no reset phase... It is just reassigning the head of branch to
point to a different commit-id. If you want to copy a branch instead of
rebasing the old one, you create a new branch (a new name) that points
to the same commit as the branch that you want to copy, after that you
rebase this new branch. You can do that like this:
$ git branch new-foo foo
$ git rebase --onto newbase oldbase new-foo
It likely wouldn't make sense to base this new "copy" feature directly
on "git rebase" though, especially in light of all the warnings about
how "git rebase" isn't friendly when applied to already published
branches. I think in theory this "copy" feature won't cause problems
for already-published branches.
The "copy" does not have the problem of rebase, but it has a different
problem: You have two series of commits instead of one. If you found
a bug in one of those commits, you will have to patch each series
separately. Also, git merge may produce additional conflicts... So,
copying commits is not something that I would recommend to do often.
Dmitry
From: Greg A. Woods <hidden> Date: 2016-06-15 22:47:48
At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov [off-list ref] wrote:
Subject: Re: "git merge" merges too much!
The key difference comparing to what you may got used is that branches
are normally based on the oldest branch in what this feature may be
included. Thus normally changes are not backported to old branches,
because you can merge them directly.
Hmmm... the idea of creating topic branches based on the oldest branch
where the feature might be used is indeed neither intuitive, nor is it
mentioned anywhere I've so far read about using topic branches in Git.
To use topic branches effectively this way, especially in managing local
and custom changes to a large remote project where separate working
directories are needed for long-running builds, I think some additional
software configuration management tool must be used to create
"configuration" branches where all the desired change sets (topic
branches) are merged.
I spent half my dreaming time early this morning running through
scenarios of how to use topic branches, with true merging (not
re-basing), in a usable work-flow.
At the moment I'm leaning towards a process where the configuration
branch is re-created for every build -- i.e. the merges are redone from
every topic branch to a freshly configured branch forked from the
locally supported release branch, hopefully making use of git-rerere to
solve most conflicts in as automated a fashion as is possible.
This may not be a sane thing to do though -- it may be too much work to
do for every fix. It somewhat goes against the current natural trend in
many of the projects I work on to develop changes on the trunk and then
back-port (some of) them to release branches.
Perhaps Stacked-Git really is the best answer. I will have to
investigate more.
quoted
quoted
Yes, you must cherry-pick or use rebase (which is a more featureful
version of the pipeline you mentioned).
"git rebase" will not work for me unless it grows a "copy" option ,
i.e. one which does not delete the original branch (i.e. avoids the
"reset" phase of its operation).
There is no reset phase...
By "reset phase" I meant this part, from git-rebase(1):
The current branch is reset to <upstream>, or <newbase> if the --onto
option was supplied. This has the exact same effect as git reset --hard
<upstream> (or <newbase>).
It is just reassigning the head of branch to
point to a different commit-id. If you want to copy a branch instead of
rebasing the old one, you create a new branch (a new name) that points
to the same commit as the branch that you want to copy, after that you
rebase this new branch. You can do that like this:
$ git branch new-foo foo
$ git rebase --onto newbase oldbase new-foo
Hmmm.... I'll have to think about that. It makes some sense, but I
don't intuitively read the command-line parameters well enough to
predict the outcome in all of the scenarios I'm interested in.
what is "oldbase" there? I'm guessing it means "base of foo" (and for
the moment, "new-foo" too)?
It's confusing because the manual page uses the word "upstream" to
describe this parameter.
From my experiments it looks like what I might want to do to copy a
local branch to port its changes from one release branch to another is
something like this (where local-v2.0 is a branch with local changes
forked from release branch REL-v2.0, and I want to back-port these
changes to a new local branch forked from the release branch REL-v1.0):
$ git branch local-base-v1.0 REL-v1.0 # mark base of new branch
$ git branch local-v1.0 local-v2.0 # dup head of src branch
$ git rebase --onto local-base-v1.0 REL-v2.0 local-v1.0
$ git branch -d local-base-v1.0
The first and last steps may not be necessary if REL-v1.0 really is a
branch, but in my play project it is just a tag on the trunk. In the
case that it were really already a branch then hopefully this would do:
$ git branch local-v1.0 local-v2.0 # dup head of src branch
$ git rebase --onto REL-v1.0 REL-v2.0 local-v1.0
The trick here seems to be to invent the name of the new branch based on
where it's going to be rebased to.
I think this does suffice very nicely as a "git copy" operation!
The "copy" does not have the problem of rebase, but it has a different
problem: You have two series of commits instead of one. If you found
a bug in one of those commits, you will have to patch each series
separately. Also, git merge may produce additional conflicts... So,
copying commits is not something that I would recommend to do often.
Indeed.
--
Greg A. Woods
+1 416 218-0098 VE3TCP RoboHack [off-list ref]
Planix, Inc. [off-list ref] Secrets of the Weird [off-list ref]
On Tue, Dec 01, 2009 at 01:52:18PM -0500, Greg A. Woods wrote:
At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov [off-list ref] wrote:
Subject: Re: "git merge" merges too much!
quoted
The key difference comparing to what you may got used is that branches
are normally based on the oldest branch in what this feature may be
included. Thus normally changes are not backported to old branches,
because you can merge them directly.
Hmmm... the idea of creating topic branches based on the oldest branch
where the feature might be used is indeed neither intuitive, nor is it
mentioned anywhere I've so far read about using topic branches in Git.
Most things that we consider "intuitive" are those that we got used to.
Git is different in many aspect than other VCSes (such as CVS/SVN), and
the workflow that good for those VCSes may not be optimal for Git. There
is a good description that provide basic knowledge how to use Git:
man gitworkflows
or online:
http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
If you do not base your changes on the oldest branch then you will not
be able to merge changes, which implies you will have to cherry-pick
manually without ability automatic to track what changes were merged
and what were not, this is a recipe for a disaster...
At the moment I'm leaning towards a process where the configuration
branch is re-created for every build -- i.e. the merges are redone from
every topic branch to a freshly configured branch forked from the
locally supported release branch, hopefully making use of git-rerere to
solve most conflicts in as automated a fashion as is possible.
I am not quite sure that I fully understood your idea of configuration
branches, but I want to warn you about one serious limitations of
git-rerere -- it stores conflict resolution per-file basis. This means
that if resolution of some conflict implies some change to another file
then git-rerere will not help you here. So, it handles maybe 80-90%
cases, but not all of them.
Perhaps Stacked-Git really is the best answer. I will have to
investigate more.
There is also TopGit. I have never used any of them, but if you are
interested in patch management system, you probably should look at both
of them. StGit is modelled after quilt, while TopGit is aimed to be
better integrated with Git and better fit to work in distributed
environment. But as I said, I do not have any first hand experience
with any of them. (Personally, I would look at TopGit first, but maybe
I am biased here).
Hmmm.... I'll have to think about that. It makes some sense, but I
don't intuitively read the command-line parameters well enough to
predict the outcome in all of the scenarios I'm interested in.
what is "oldbase" there? I'm guessing it means "base of foo" (and for
the moment, "new-foo" too)?
You have:
o---o---o---o---o newbase
\
o---o---o---o---o oldbase
\
o---o---o foo
and you want this:
o---o---o---o---o newbase
| \
| o´--o´--o´ new-foo
\
o---o---o---o---o oldbase
\
o---o---o foo
Dmitry
Hmmm.... I'll have to think about that. It makes some sense, but I
don't intuitively read the command-line parameters well enough to
predict the outcome in all of the scenarios I'm interested in.
what is "oldbase" there? I'm guessing it means "base of foo" (and for
the moment, "new-foo" too)?
You have:
o---o---o---o---o newbase
\
o---o---o---o---o oldbase
\
o---o---o foo
Yes, sort of -- in the ideal situation, but not in my particular example
where "oldbase" is just a tag, not a real branch.
So yes, "oldbase" is in fact "base of foo". Trickier still is when the
"oldbase" branch has one or more commits newer then "base of foo". Does
Git not have a symbolic name for the true base of a branch? I.e. is
there not some form of symbolic name for "N" in the following?
o---o---o---o---o---o---o---o master
\
o---o---N---o---o release-1
\
o---o---o local-release-1
(now of course if it is discovered that "release-1" has progressed since
the base of "foo" then "foo" should be rebased first, but perhaps there
is not time to do this before the other release has to be supported)
and you want this:
o---o---o---o---o newbase
| \
| o'--o'--o' new-foo
\
o---o---o---o---o oldbase
\
o---o---o foo
Yes, sort of I suppose, if you trim all the non-relevant branches.
What I really want, I think, is something like this where at least the
non-relevant "master" branch is still shown:
1'--2'--3' new-foo
/
o---o---o newbase
/
o---o---o---o---o---o---o---o master
\
o---o---o oldbase
\
1---2---3 foo
Here's part of my confusion -- "newbase" as used above is actually older
than "oldbase". :-) so ideally "oldbase" should always be described in
terms of "foo", not just given an arbitrary unrelated name.
Of course that doesn't rule out the following scenario either where
"newbase" really is newer than "oldbase" -- in my world a given project
might become locally supported first on either a newer release, or an
older release, so both above and below might happen:
1'--2'--3' new-foo
/
o---o---o newbase
/
o---o---o---o---o---o---o---o master
\
o---o---o oldbase
\
1---2---3 foo
And eventually I want to also merge whatever is still relevant from foo
to a "local" branch off master so that those changes can be sent
(usually as patches) upstream.
Sometimes I want to do development on a topic branch as close to the tip
of "master" so that it can most easily be pushed upstream, and then
back-port those changes to older release branches.
In fact the latter is exactly how I picture release branches to work in
normal development, and this is how several of the big projects I'd like
to get using Git are doing development (now usually with CVS).
Note too that in these kinds of projects "topic" branches are _always_
forked from the current tip of "master", long-running ones sometimes
rebased to keep up with "master", small fixes and changes are made
directly to the master branch; and small fixes, as well as relevant
features, sometimes those developed on "topic" branches, are back-ported
to release branches.
Note I'm not talking about ideals of best practises specific for Git
here -- I'm talking about actual working operational practises that
people are _very_ familiar with and which have been well proven using a
vast wide variety of different VCS's in the past. For example I
seriously doubt any of the developers of the projects I'm thinking of
that I'd like to switch to using Git are ever going to want to fork
their topic branches from the oldest release branch base that they
intend to support, and many such projects will necessarily always have
at least a few long-running topic branches that will have to be
frequently rebased to keep up with the trunk so that their eventual
merging will go as smoothly as possible, and yet once any of these topic
branches is finally "closed" their changes may also have to be
back-ported to release branches.
To me the natural way to do these kinds of back-porting "merges" is to
restrict the merge to select only the commits on the branch, i.e. from
its base to its tip, thus the motivation for the topic of my thread (and
I think the motivation for the "What is the best way to backport a
feature?" thread as well). I think if Git could do this kind of
"partial" merging directly without having to "copy" deltas with "rebase"
or "cherry-pick" or "am" or whatever, and thus create separate histories
for them, then it would be much better at supporting this traditional
practice of using branches to manage releases. Without such ability it
truly does look as though some form of "patch" management tool is also a
necessary thing(evil?), as "rebase" and "cherry-pick" could quickly get
way out of control and be way too much work otherwise.
--
Greg A. Woods
Planix, Inc.
[off-list ref] +1 416 218 0099 http://www.planix.com/
Hmmm.... I'll have to think about that. It makes some sense, but I
don't intuitively read the command-line parameters well enough to
predict the outcome in all of the scenarios I'm interested in.
what is "oldbase" there? I'm guessing it means "base of foo" (and for
the moment, "new-foo" too)?
You have:
o---o---o---o---o newbase
\
o---o---o---o---o oldbase
\
o---o---o foo
Yes, sort of -- in the ideal situation, but not in my particular example
where "oldbase" is just a tag, not a real branch.
It does not matter whether it is tag or branch or just SHA-1. You can
use any two reference as newbase and oldbase. They specify two points
in DAG. The only thing that has to be a branch in my example is new-foo.
So yes, "oldbase" is in fact "base of foo". Trickier still is when the
"oldbase" branch has one or more commits newer then "base of foo". Does
Git not have a symbolic name for the true base of a branch? I.e. is
there not some form of symbolic name for "N" in the following?
o---o---o---o---o---o---o---o master
\
o---o---N---o---o release-1
\
o---o---o local-release-1
You can always find SHA-1 for N using the following command:
git merge-base release-1 local-release-1
but you do not have to do that to rebase your changes. You just can run:
# create a copy of local-release-1, so it will not disappear
git branch copy-release-1 local-release-1
# rebase the branch to master
git rebase --onto master release-1 copy-release-1
Dmitry
At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov [off-list ref] wrote:
Subject: Re: "git merge" merges too much!
quoted
The key difference comparing to what you may got used is that branches
are normally based on the oldest branch in what this feature may be
included. Thus normally changes are not backported to old branches,
because you can merge them directly.
Hmmm... the idea of creating topic branches based on the oldest branch
where the feature might be used is indeed neither intuitive, nor is it
mentioned anywhere I've so far read about using topic branches in Git.
You may want to add the result of googling
"Fun with" site:gitster.livejournal.com
to the list of Git documents you read. "Fork from the oldest
branch" is one of the techniques Junio teaches often and many
of his other techiniques are built upon.
He not just teaches useful techniques but explains a lot about
the reasoning behind them in his Git book. His blog articles
have the same explanations on many topics I saw in his book
but not in other places. It is a useful substitute until his
book gets translated to English for people who don't read
Japanese.
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
From: Jeff King <hidden> Date: 2016-06-15 22:47:49
On Mon, Nov 30, 2009 at 01:12:31PM -0500, Greg A. Woods wrote:
(From a first pass through the documentation I would never have guessed
that "tags" were also a form of "refs". All these different names for
I find git is much simpler to use and understand if you start "at the
bottom" with the basic concepts (because for the most part, git is
really a set of tools for manipulating the few basic data structures).
For a short intro, try:
http://eagain.net/articles/git-for-computer-scientists/
I think Scott Chacon's "Pro Git" book also takes a similar approach, but
I confess that I have not actually read it carefully. At this point, I
know enough about git to make reading it not very interesting. :) You
can find it online at:
http://progit.org/book/
features. Even the gitglossary(7) is somewhat inconsistent on how it
uses "ref" and "refs". Perhaps all that's needed is some firm editing
and clean-up of the manuals and documentation by a good strong technical
editor.)
I skimmed it and didn't see any inconsistency. If you have something
specific in mind, please point it out so we can fix it.
"git rebase" will not work for me unless it grows a "copy" option ,
i.e. one which does not delete the original branch (i.e. avoids the
"reset" phase of its operation). This option would likely only make
sense when used with the "--onto" option, I would guess.
I think Dmitry already mentioned this, but you probably want to create a
new branch to hold your rebased history if you don't want to modify the
existing branch.
(git-log(1) is worse than ls(1) for having too many options, but worst
of all in the release I'm still using it doesn't respond sensibly nor
consistently with other commands when given the "-?" option.)
$ ls -?
ls: invalid option -- '?'
Try `ls --help' for more information.
$ ls --help ;# or ls -h
[copious usage information]
$ git log -?
fatal: unrecognized argument: -?
$ git log --help
[the man page]
$ git log -h
usage: git log [<options>] [<since>..<until>] [[--] <path>...]
or: git show [options] <object>...
$ cd /outside/of/git/repo
$ git log -?
fatal: Not a git repository (or any of the parent directories): .git
So "-?" is bogus for both ls and git. But there are two failings I see:
1. Outside of a repository, "git log" does not even get to the
argument-parsing phase to see that "-?" is bogus. We short-circuit
"-h" and "--help" to avoid actually looking for a git repository,
but obviously cannot do so for every "--bogus" argument we see.
We could potentially also short-circuit "-?" (and probably map it
to "-h" if we were going to do that). However, I didn't think "-?"
was in common use.
2. "git log -h" doesn't mention any of the options specifically,
though other git commands do (e.g., try "git archive -h"). This is
because the option list is generated by our parseopt library, but
the revision and diff options (which are the only ones that "git
log" takes) do not use parseopt. Maybe we should point to "--help"
for the full list in that case.
-Peff
From: Greg A. Woods <hidden> Date: 2016-06-15 22:47:49
At Wed, 2 Dec 2009 15:09:04 -0500, Jeff King [off-list ref] wrote:
Subject: Re: "git merge" merges too much!
I find git is much simpler to use and understand if you start "at the
bottom" with the basic concepts (because for the most part, git is
really a set of tools for manipulating the few basic data structures).
I think that's the problem actually -- I don't really want to know too
much about how it works under the hood (yet), I just want to use it in
the most effective way for my purposes.
There's lots of talk about using Git as the basis for a true high-level
VCS and SCM system, yet it doesn't look to me that anyone has created
such a VCS or SCMS using Git.
I skimmed it and didn't see any inconsistency. If you have something
specific in mind, please point it out so we can fix it.
I think anyone who's been participating on this list for any significant
amount of time is far too close to the subject to be able to serve as a
candid independent technical editor who could really help clean things
up and make the documentation much more consistent. Obviously such an
editor would also require the help of experts at all the details too. :-)
Unfortunately I'm not a very good technical editor, and I don't really
have time to devote to doing such editing of documentation either.
quoted
(git-log(1) is worse than ls(1) for having too many options, but worst
of all in the release I'm still using it doesn't respond sensibly nor
consistently with other commands when given the "-?" option.)
$ ls -?
ls: invalid option -- '?'
Try `ls --help' for more information.
Please keep in mind all the world is not GNU:
$ ls -?
ls: unknown option -- ?
usage: ls [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]
My point was that _most_ other Git sub-commands already do respond to
"-?" sensibly with real, helpful, information; usually a summary of the
command options and parameters.
I.e. this is yet another form of inconsistency in "documentation" in
Git. :-)
The reference to "ls" was just as a comparison with it's somewhat
extensive variety of options. In fact "git log" is way more complex
than "ls" because its parameters are not all just simple flags like
those for "ls" -- they often have their own parameters too.
Indeed, so why the heck can't it do something similar with '-?'. That's
just sloppy programming, no? Most other commands know '-?', and despite
the silliness with GNU Ls, use of '-?' to request summary usage
information is pretty much a de facto standard for unix commands.
Your point about mentioning "--help" in the summary usage information is
a good one though -- especially for a command with a very complex set of
command-line parameters. However that alone isn't sufficient -- users
still need the summary as that alone helps trigger associations and may
be sufficient to allow a user to proceed quickly to get the command to
do what they want.
(the whole "fatal: not a git repository" error for "git foo -[h?]"
handling is also a rather silly one -- but I guess when something grows
quickly and from many inputs there's not always time to keep some of
these basic things clean and consistent)
--
Greg A. Woods
Planix, Inc.
[off-list ref] +1 416 218 0099 http://www.planix.com/
From: Jeff King <hidden> Date: 2016-06-15 22:47:49
On Wed, Dec 02, 2009 at 08:21:39PM -0500, Greg A. Woods wrote:
quoted
I find git is much simpler to use and understand if you start "at the
bottom" with the basic concepts (because for the most part, git is
really a set of tools for manipulating the few basic data structures).
I think that's the problem actually -- I don't really want to know too
much about how it works under the hood (yet), I just want to use it in
the most effective way for my purposes.
There's lots of talk about using Git as the basis for a true high-level
VCS and SCM system, yet it doesn't look to me that anyone has created
such a VCS or SCMS using Git.
Sure, I can understand that. And I invite you (or anyone) to work on
such a VCS, and I am sure I am not alone on the list in sincerely hoping
you succeed and offering to help support however core git developers
can. But we have seen people try this in the past, and it never quite
seems to work.
All of the cogito people ended up migrating to git. I was one of them.
In my case, the git tools offered better access to the fundamental
operations, which is what I found interesting and powerful about it. I
suspect some others migrated for the same reasons, though perhaps many
did simply because cogito did not keep up with core git in terms of
features.
There is also "eg" these days, which attempts to do what you're saying.
I don't know how big a userbase it has; I've never been personally
interested in it.
I think anyone who's been participating on this list for any significant
amount of time is far too close to the subject to be able to serve as a
candid independent technical editor who could really help clean things
up and make the documentation much more consistent. Obviously such an
editor would also require the help of experts at all the details too. :-)
Sure, I think an outsider doing a really nice job of overhauling the
documentation would be nice. There are some git books, some by insiders,
and some not. For the same reason that you mention, it would hard for me
to assess their quality with too much objectivity. :)
My question was more of a "leaving aside overhauling the documentation,
did you see something obvious that we can fix right now" kind of thing.
quoted
$ ls -?
ls: invalid option -- '?'
Try `ls --help' for more information.
Please keep in mind all the world is not GNU:
$ ls -?
ls: unknown option -- ?
usage: ls [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]
Right, but my point is unchanged. Neither ls actually _recognizes_
"-?". They do the same for "--bogosity".
My point was that _most_ other Git sub-commands already do respond to
"-?" sensibly with real, helpful, information; usually a summary of the
command options and parameters.
Yes, for the same reason that "ls" does: they don't recognize it. But if
you are asking for "git log" to produce the short usage message, then
that is part of my issue (1) from the last message: "log" doesn't use
the same parseopt library as (most of) the rest of git[1].
Yes, it's inconsistent. Those inconsistencies were introduced over time
(before we had parseopt), and we are slowly fixing them over time.
Patches welcome. :)
[1] There are other inconsistencies because of this, too. You can't say
"git log -pz", but must say "git log -p -z".
Indeed, so why the heck can't it do something similar with '-?'. That's
just sloppy programming, no? Most other commands know '-?', and despite
the silliness with GNU Ls, use of '-?' to request summary usage
information is pretty much a de facto standard for unix commands.
Nothing "knows" -?, but it is true that the parseopt-ified commands
behave differently (and IMHO, better). You can call it sloppy, I guess;
it is really an artifact of commands being written and changing over
time. As I said, we are slowly converging on consistency.
And no, I don't want to get into a big debate over whether it is better
to plan your software up front, or to let it evolve over time. I have
opinions that do not necessarily line up with how git came into being,
but the end product is useful enough that I like to use it and hack on
it. :)
(the whole "fatal: not a git repository" error for "git foo -[h?]"
handling is also a rather silly one -- but I guess when something grows
quickly and from many inputs there's not always time to keep some of
these basic things clean and consistent)
The problem here is that there are two chunks of code: the "git"
wrapper, and the "log" command. The wrapper knows a few things about
each command like "does it need to be in a git repository?", and checks
that before we even look at the command-line options. There is an
explicit "check for --help" hack. Fixing that startup procedure to be
more sane would be possible, but there are a lot of hidden demons
lurking in changing the order of the startup sequence. Again, patches
welcome. :)
-Peff