Reputation: 291
I need to get list of commites, which pushed, for example, in 'task/105' branch.
I mean, i need get commites, pushed to 'task/105' branch, in range from first commit in 'task/105' branch, to the last.
I tried to do following:
git /dir/project
git checkout task/105
git log task/105
But it not help. It show to me commites for another branches and for 'test' branch both.
I readed, what i need to do something like this:
git log TASK_105_FIRST_COMMITE..task/105
But id dont know, how to get first commit for task/105 I readed, what it can help:
git merge-base master task/105
git log as65g76s5dgsd5gsd6sd65g4s...task/105
But i confused by the word 'master'. How if commit in master pushed after pushing commites in task/105?
Finally, i really don't know what to do... Sorry for bad english
Upvotes: 0
Views: 82
Reputation: 487805
(I'm not sure what you mean by "first commit", and "pushed" makes me think you might be looking at a more restricted situation.)
In general, to mark particular commits with a name, one should use git's "tags", or a reference that "acts like" a tag.
Here's a bit of basic necessary background:
bd5d3781a8e32d3627bb1de70dc6b105dc9d77a0
(often shortened to the first 7 characters).refs/heads/master
and refs/tags/v1.3
. You can usually omit the refs/heads/
and refs/tags/
parts as well.A branch or tag name is really just a way to specify the SHA-1, with one other exception:
refs/heads/
namespace—is automatically moved when needed. (A "remote" branch, in refs/remotes/
, also moves when you fetch
from the remote. More generally the idea is that "branches move but tags don't".)Adding a new commit, git commit -m 'fix some bug'
, looks up the current branch—which could be master
, or could be task/105
, or any other valid branch-name string; it's a branch if it's prefixed by the usually-invisible refs/heads/
part. Having found the current branch (and its corresponding SHA-1 value), the git commit
command writes a new commit into the repo, whose parent is the then-current SHA-1. The new commit has a new unique SHA-1 value, and git commit
then changes the branch name to point to the new commit, which people call "moving the branch forward".
Git does not2 record the "old value" of the branch here. It just changes the branch name -> SHA-1 mapping. So how can you tell which commit the branch used-to point to? The answer is that you can't, not with 100% reliability (see footnote 2).
If you need to mark a commit with a name, this is what "tags" are intended for. There are two kinds of tags: "annotated" tags (which actually reside inside the git repository and can be authenticated if necessary), and "lightweight" tags.
A lightweight tag consists of an external name that lives in the refs/tags/
namespace, pointing to a commit, just like a branch except that it does not move automatically. (You can move it manually, with the "force" flags.)
An annotated tag consists of an external (lightweight) tag that points to a git repository object of type "tag", which carries information much like a git commit object: date, author, and so on. However, a commit object "points to" a tree, while a tag object "points to" a commit object (which then points to a tree).3
With all that in mind, what people call "a branch" is usually a piece of a commit graph. A commit graph is formed by taking all the externally-referenced commits (those with branch and tag names, plus a few other special cases) and "working backwards" along the parent references to find more commits. This can be written or drawn something like this:
o--o--o
/ \
...--o--o--o--o---o--o <-- refs/heads/master
\
o <-- refs/tags/v0.9
\
o--o <-- refs/heads/devel
Here the little o
s depict commit nodes and the <--
arrows show externally-referenced commits.
Thus, if you have a single repository (on your development machine, for instance) and want to know which commits happened "after point X
" and "through the tip of branch pointed-to by name Y
", you must save (somewhere) the "true name" (SHA-1) for "point X
". Let's say that "point X
" was captured earlier when we made the tag v0.9
, and that "point Y
" is actually "branch devel
". Then:
v0.9..devel
is standard git revision-string shorthand that means "all commits reachable from the name devel
, excluding all commits reachable from the name v0.9
". Since v0.9
is a valid tag, this will get you just the bottom-most two o--o
commits.
Asking for master..devel
will get you "commits reachable from devel
, excluding commits reachable from master
". It is not important that there are commits reachable from master
that are not reachable from devel
: you can think of this as taking a colored marker and drawing "backwards" from refs/heads/master
, coloring in all the commits that can be reached by moving leftwards in the drawing (but never moving rightwards). Then you take a second, different color and color in all the commits from refs/heads/devel
but don't re-color any already-colored commits. So in this case, master..devel
gets you three commits: the one named by refs/tags/v0.9
, plus the bottom two commits.
Now, you keep mentioning "pushed", which brings in a new and different wrinkle. When you run git push origin branch
, there are two repositories involved: yours, with your refs/heads/branch
name, and "origin" (at some other URL), with his refs/heads/branch
name.
If the push is successful at updating (and not "creating") his refs/heads/branch
, that means he had some previous SHA-1 identified by refs/heads/branch
, and once the push finishes, he has some new and different SHA-1 identified, specifically, the one you just pushed successfully.
If you want to know "what commit did his refs/heads/branch
point to before I changed it", well, he's the only one who knows that. The best way to find out is to ask him. You can use git ls-remote
to do this, or git fetch
. In general you should fetch before pushing anyway, so that's probably the appropriate option. There is a problem here though, as there's a race between what he tells you when you ask (ls-remote
or fetch
) and what he has when you finally get around to git push
-ing. Even if you work really fast, in the few milliseconds between your query and your push
, someone else could sneak in and do a different push
and change things. So the best way to find out what got updated "on his side" is to have him tell you, generally through a "post-receive hook". (This hook gets handed "old-SHA-1, new-SHA-1, ref-name" triples.)
1In fact, there are two separate dates and user names, one for "author" and one for "committer". Try git cat-file -p HEAD
to see the (mostly-)raw data inside a commit.
2Actually, git does record the old value, in the "reflog" ... but reflogs are not permanent. If you need to recover a forgotten SHA-1, within the expiration time, it's there; but if you want it as a more permanent item, that's not what the reflog is meant for, and it will be awkward to use it that way.
3In fact, tags can point to more (annotated) tags, and that's considered normal usage. It's also physically possible to point any reference to a "tree" or "blob" inside the repository, but those are not normal uses for refs/heads/
and refs/tags/
references.
Upvotes: 3