简体   繁体   中英

Commits on Tag and How It Merges with the Latest Version of Git Repository

Okay, I'm not that familiar with Git. I was asked to clone a repository from someone's repository and then use the tag. So here's what I did:

git clone someones_repo my_new_repo
git checkout tags/bla_bla_tag -b tag_branch

So now I'm in the tag version and not in the master branch but in the tag_branch.

I did changes and want to commit them and merge them with my master and then turn in my changes to our official repository (I think they call this golden repo). And here are my worries:

  1. This "master" branch, does it contain the latest version of the repo that I cloned? Or does it contain the version of the tag?
  2. If the master is the version of the tag, and then I merge my changes to it, then what will happen if I turnin these merged changes to our official repo? Will the latest version of the official repo becomes the version of my merged changes?If anyone tries to clone the official repo, then will he get my merged version instead?.

When you create a branch off of a "tag", you create a pointer to a commit. The tag points to a commit and your branch is like a pointer to this commit as well. If this commit is on the master branch or not is impossible to say without more information.

To get the latest master you can do git fetch and the latest master will be in origin/master .

For example, if you have created one commit based on the tagged commit, you can deliver it by:

git checkout master
git pull -r
git cherry-pick <your commit>
git push origin master

In plain english this would mean. Checkout local master. Update local master to match remote master. Put your new commit ontop of local master, and update local master to point to this commit. Deliver local master to remote master.

I am not sure what you meant by "turn in the changes to the main repo". I am hoping its a pull request and not a push directly to the golden repo

  1. The master of your local branch will be the same as that of that someone's repo. It may be the same as the master of the golden repo, if those two repos are kept in sync regularly.

  2. A tag is just a label you add to some commit, usually for a commit in master. If your pull request is merged, the master in golden repo will become your version of master. And if someone clones the golden repo they will get your request version.

I would recommend using the pull request workflow for this. Otherwise the chance of losing commits are very high

There are a few good answers already, but what you really could use here is a graphical illustration.

The key to understanding how branches and tags work in Git is to realize that the branch and tag names are mere auxiliaries. They do very little to actually make branches. The very word "branch" itself is actually ambiguous in Git. To see more about this, and several diagrams, click on What exactly do we mean by "branch"? This describes how branch labels select particular commits, although not the process by which a branch grows . (Note also that the first image from the Pro Git book is fine, but like Jubobs, I dislike the second Pro Git image.)

I use a simpler diagramming method in StackOverflow postings. Take this example diagram of a repository with just three commits. Each of these three commits has an actual hash ID—one of those big ugly 40-character things that abbreviate to badf00d and cafedad and so on—but I just give them one-letter names, and put the branch name on the right:

A <- B <- C   <-- master

Here C is our latest commit, on branch master . The branch name master contains the actual hash ID of commit C , such as ac0ffee4cafedad5badf00d... or whatever. Commit C itself—the actual commit, stored inside Git's database—has in it the ID of commit B . We say that master points to C , and C points to B . B has the ID of A , so it points to A . A was the very first commit anyone ever made, so it cannot point anywhere. It has no parent , in Git's terms; it is a root commit .

Note that in this system, parent commits don't know which children they have, but children do know their parents. To make a new commit on master , Git writes some things into the database, ending with the new commit object. The new commit—let's call it D —contains the current commit's ID as its parent, so that D points back to C . Then Git updates the branch name , master , so that it points to D :

A <- B <- C <- D

(As someone pointed out recently, this is a lot like digging through genealogy records: you find something like "Bob Jones, born to parents Arthur and Sally". Obviously Bob's birth record can't list that 25 years later he will have a daughter, so it just doesn't. Similarly, when you make a commit, Git knows who the commit's parent is, but it has no idea whether the commit will have children.)

With that in mind, consider this graph fragment. I've stopped drawing the internal arrows to save space and such, but remember, they always point backwards (leftwards in these drawings):

...--D--E--F   <-- master
      \
       G--H    <-- sidebr

We get here by making two new commits on master , ie, E and F , but also by creating a new branch name , sidebr , pointing to commit D . Then we git checkout sidebr and make two new commits. These are G and H . When we make G , commit D is current, and is what sidebr points-to. So Git writes the commit with D as its parent and changes sidebr to point to G . Now that G is current, we make new commit H with G as its parent, and update sidebr to point to H , and that's how we got to this diagram.

Time for tags

Now is the time to add tags to these pictures. Tags are almost (but not quite) the same as branches. Like branch names, tag names point to commits. The key difference 1 is that branch names are supposed to move: they grow automatically, by adding new commits. Tag names are not supposed to move.

As a result, we might as well draw them "inside" the commit diagram, rather than way over on the right. (Or, if we had color, we could use different colors for branch and tag names—but I cannot do color in text on StackOverflow.) So let's add a tag name pointing to commit E :

     tag:v0.1
        |
        v
...--D--E--F   <-- master
      \
       G--H    <-- sidebr

This tag points to commit E . It should always, forever-more, point to commit E . 2 There's an interesting fact about raw Git hash IDs that is quite relevant here: the hash ID is totally deterministic, and is based entirely upon the actual contents of the commit (or other Git object). Tag names therefore do little more than provide a human-readable name for one of those awful hash IDs. If we could all just remember 17f9f635c101aef03874e1de1d8d0322187494b3 , we would not need the tag v2.6.0 in the Git repository for Git—but I'm certainly not going to remember that. 3

In any case, you can git checkout any commit by its ID, or by anything that resolves to its ID. A tag name works for the latter, and of course, is much easier to remember. So, given the above diagram, we can check out commit E with:

git checkout v0.1

(the tag: is not part of the tag name, just something I wrote to say why we have an arrow here). This, however, gives us a "detached HEAD", so that's why we git checkout -b newbranch v0.1 : that assigns a new branch name to point to the commit. Now we need to re-draw the graph a bit to give more room:

     tag:v0.1
        |
        |  F   <-- master
        v /
...--D--E      <-- newbranch (HEAD)
      \
       G--H    <-- sidebr

I also added this HEAD thing: that's a reminder that we're now on this new branch. If we make a new commit now, this will grow the branch in the usual way:

     tag:v0.1
        |
        |  F   <-- master
        v /
...--D--E--I   <-- newbranch (HEAD)
      \
       G--H    <-- sidebr

The tag—which is not supposed to move—does not move. The branch , however, does move. We can make whatever commits we like, and each one makes the current branch— newbranch —advance to incorporate each of our new commits.


1 Another important difference is that tag names live in a shared name space, across all repositories, while branches don't. There are also annotated tags , which give you the opportunity to attach some uninterpreted data, and Git lets you sign such tags using GPG encryption. But that's for another discussion.

2 It's possible to forcibly move a tag, or to remove it and re-create it pointing to a different commit. Sometimes there is even a good reason to do that. You just need to be sure the reason is especially good, because the tag is really just a human-readable name for the hash ID, and any repository that already has the old tag, is likely to think the old tag-to-hash-ID mapping is still correct, even after you have forcibly moved the tag.

3 I used git rev-parse v2.6.0 to find it. The hash ID above is the ID of the annotated tag object (which you can find by cloning the Git repository for Git). The actual commit is be08dee9738eaaa0423885ed189c2b6ad8368cf0 . There is special syntax for finding the commit ID in one step, using git rev-parse , or you can use git show v2.6.0 to read the tag object, and then git show the tag's target object to see the commit, for instance.

For your questions:

  1. For the repo you cloned, it only can be sure that the time you cloned is the newest version. If you colleague make some changes for his repo after you cloned, then your local repo is not the latest version. And the cloned repo contains tags which exist in your colleague's repo. There is a way to check if your local repo is latest version by:

git fetch origin git log master..origin/master

If there has output, that means your local master is not the latest version, you should use git pull to pull changes.

  1. If the tag you use is on master branch, and you merge your changes into master, the latest version for official repo will become the new version you merged. And after that, if anyont clone the official repo, master branch latest version is also the version you merged.

PS: If both you and your colleague are work for official repo, you should clone from official repo at the first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM