cohsta
cohsta

Reputation: 187

git checkingout a branch then make that branch to head/master

Let's say I made the most recent commit and pushed it to the my private repository, how do you go back to the branch you want to checkout and then push it to the head/master of the repository??

git checkout branch_name

and what command do I have to do to move that branch_name to the master/head ?

Upvotes: 0

Views: 649

Answers (4)

torek
torek

Reputation: 488183

Based on this comment:

Okay, so I checkout my_branch, i add the change and commit it and whenever I do git push origin master, it says everything up to date.. How do I make it so whenever I pull it from the other remote computer, the changes I made pulls?

What you need is a good tutorial, really, but unfortunately there are a lot of bad tutorials and not that many good ones. I recommend the Pro Git book. It is a lot to read and digest, though.

For the moment, let's just go through what you have so far and make a few short (I hope) notes on what they do. Let's start by noting that there are at least two repositories involved here, yours—your clone, that you made with git clone—and the one on some other machine that you access under the name origin. Pretty much everything you do happens in your clone, except for git push (package up commits from your clone, deliver them to the remote, and ask the remote to change one of its branch names to point to them), and a bit of git fetch (we'll get to this in a moment).

What you have done so far

First:

git checkout my_branch

This tells Git to look up the name my_branch, which we can assume here is an existing branch in your repository.

Assuming this succeeds, Git sets HEAD to point to my_branch. The name my_branch points to some particular commit, so diagrammatically, we have:

...(some commits)<-o<-o   <-- HEAD->my_branch

where the os represent the commits. Each commit points back to its parent commit, and my_branch points to the tip-most (right-most) such commit. Git can then find all the commits by starting from HEAD, seeing that it points to my_branch, seeing where my_branch points (that tip commit), and then following each commit to its parent.

Next, you add/modify some files, maybe remove a file or two, and eventually commit:

...
git add ...
...
git commit

This makes a new commit. The process of making a new commit works by reading HEAD as usual, finding that it points to my_branch, reading my_branch to find its commit (the current tip of the branch), and then making the new commit out of whatever is in the index/staging area (the stuff you git add-ed above). As a final step, git adjusts my_branch to point to the new commit.

Let's draw that diagram again, with the new commit in it. Let's draw the new commit as * instead of just o, so that we can easily see which one it is:

...(some commits)<-o<-o<-*   <-- HEAD->my_branch

So far so good, but all this is strictly in your own repository, so now we get to your question about git push. Here, things get a little bit complicated.

You ran this:

git push origin master

but we just said, and drew, above, that HEAD points to my_branch and my_branch points to this new * commit. Where is master in all of this?

Well, we didn't draw it earlier, and I don't have your repository so I have to guess. But let me guess that master points to the o that used to be the tip of my_branch. In order to draw this, I can't quite draw arrows any more (they aren't in the character set I have on StackOverflow), so I will just use \:

...(some commits)<-o<-o     <-- master
                       \
                        *   <-- HEAD->my_branch

This is the same drawing as before, except that (1) I had to use two lines and (2) I added the master branch to it.

When you run git push origin master you ask your Git to call up origin's Git and send it some commit(s), namely any commits you have on master that they don't have on master. But you and they have the same commits on master, so your git says "everything up to date" and stops.

What you have here is a new commit on my_branch.

(Also, the commit before your new one is on both my_branch and master, at least in the drawing I just made. I don't have your repository, so I am just guessing. But it is almost certain that some commits are on both branches. This is something unusual about Git, as compared to other version control systems. It's important later, and something to keep in mind: commits can be on many branches. For now, it's just an oddity.)

What else you can do: part 1

So, what can you do to get your new commit onto origin? One thing you can do is push it under the name my_branch. If origin has no branch named my_branch, this will create it there. If origin does have a my_branch, this will attempt to set their my_branch to point to your new commit *—after, of course, first delivering that commit. Either way:

git push origin my_branch:my_branch

or:

git push origin -u my_branch:my_branch

will try that request. Their Git can accept or reject the request, and will usually do so on the basis of whether they have a branch named my_branch (and if so, where it points right now).

Note the repetition in my_branch:my_branch. The name on the left of the colon : character is the branch name in your repository, and the name on the right is the one you are asking them—the Git on the remote named origin—to set. These two names do not have to be the same! If they are the same, you can usually just write it once though, and that's what we saw with git push origin master. You can do this with my_branch too. I like to include the colon and destination name, at least with new users, since I think it makes what's happening more obvious.

More of what else you can do: part 2

You can also do any of several other things:

  • make your new commit appear on your master (in one of several ways depending on how your repository looks right now); or
  • copy your new commit to another, even-newer commit that you add to your master; or
  • ask them (origin) to take your new commit that you have on my_branch and add it to their master.

The last one is equivalent to doing the first one, then doing git push origin master.

How to get your new commit on my_branch onto (your) master

There are two ways to do this, which can do very different things.

  1. git merge: this has two main sub-modes. It can do a real merge, or it can do what Git calls a fast-forward, which is actually not a merge at all.

  2. git reset: this has a lot of sub-modes, and is a very sharp tool that can cause a lot of grief if misused. The mode we will talk about here (but not actually use) is to note that what it does is, in a way, much like the last step git push asks the remote to do. It tells Git to peel a branch label off of whatever commit it points to now, and instead make it point to some other commit.

Let's look at git reset first, specifically, the "peel off and replace label" operation. Let's draw that graph yet again, too:

...(some commits)<-o<-o     <-- master
                       \
                        *   <-- HEAD->my_branch

First, we need to make HEAD point to master, which we do with git checkout as usual:

git checkout master

which results in:

...(some commits)<-o<-o     <-- HEAD->master
                       \
                        *   <-- my_branch

Now, suppose we were to run git reset --hard my_branch (let's not actually do it, just look at what it would do if we ran it). This tells git "peel the current branch label" (read READ => it's master) "off of the o commit it points to now and make it point to the same commit as my_branch". That is, if we ran this command, we would get:

...(some commits)<-o<-o
                       \
                        *   <-- my_branch, HEAD->master

Note that the label is moved, but nothing else has changed—the commits that are in the repository are all still the same.

git merge

Now let's go back to git merge. Unfortunately, git merge is a fairly complicated operation when it does a real merge. Fortunately, the first thing git merge does is to check whether it's a very simple operation.

Assuming the graph we have been drawing all along is accurate, this merge is a simple operation. In particular, my_branch points to a commit that we can reach by "sliding the label fast forward", against the direction of all the arrows, so that it points to commit *:

...(some commits)<-o<-o
                       \
                        *   <-- my_branch, HEAD->master

This, as it turns out, is the same as what git reset would do, but because git merge first checks to see if this is a safe thing to do, it's the command we probably wanted to use here.

Let's also look at the case where it is not safe, just for completeness. For instance, suppose we actually have this:

...(some commits)<-o<-o<-o   <-- HEAD->master
                       \
                        *    <-- my_branch

In this case, git merge will do a real merge, while git reset --hard would just throw out the final o commit on master. We can't slide the label forward, we have to back it up first, so the motion from "where master is now" to my_branch is not a fast-forward, and git merge will do a real merge.

git cherry-pick

Finally, just for completeness, let's look at how to copy the commit.

In general, to copy a commit, we use git cherry-pick. We first get on the branch we want to copy to, such as master:

...(some commits)<-o<-o<-o   <-- HEAD->master
                       \
                        *    <-- my_branch

and then run git cherry-pick my_branch. This finds the commit to which my_branch points (our * commit) and makes a copy of it, adding the copy to the current branch (read HEAD, see master, current branch is master, copy gets added to master). The result looks like this:

...(some commits)<-o<-o<-o<-x   <-- HEAD->master
                       \
                        *       <-- my_branch

where x is a copy of *.

In all of these cases, we can now git push origin master to push the original commit * or its new copy x to origin, and then ask origin to reset its master to our new commit.

pull vs fetch

You mentioned "pulls". I recommend re-learning this as two separate steps, because git pull is really just these two steps:

  1. git fetch
  2. git merge (or, usually a better command to use, git rebase)

It's actually the git fetch step that contacts the remote, origin in your case, and obtains new stuff from them.

The fetch operation brings over commits they have that you don't (and doesn't bother bringing over commits that they have that you already have). Then—this is where it is not a mirror image of git push—your git fetch copies their branch information, but renames it. Their master becomes your origin/master; if they have a my_branch, it becomes your origin/my_branch.

This renaming step is critical to allowing you to merge (or rebase). If fetching just overwrote your branches, you would lose the work you did making the new commits!

Once the fetch is done, you can then merge-or-rebase your work into/onto the new commits you brought over.

I will leave all of the description of rebasing to other postings (or the Pro Git book), but will add this last bit: besides making it clearer what's happening, the reason to keep git fetch separate from the second step is that this gives you the chance to decide which step to use.

If you know you will use git rebase, you can combine the two steps by running git pull --rebase.

If you know you will run git merge, you can combine the two steps by running git pull (with no flag).

But what if you want to look first, and then decide? Then you need to use the two separate steps, and insert the "take a look, then decide" part between those two steps. If you start with git pull, you cannot do this.

(Once you have used Git for a while, you will probably know which command you will use after git fetch. It will probably usually be git rebase, actually—and you can configure Git to use --rebase automatically. But wait until you have used Git for a while.)

Upvotes: 0

CodeWizard
CodeWizard

Reputation: 142094

Lets see if i understand you correctly.
If you wish to go back to previous commits you have this answer which explain in details what to do.

How to move HEAD back to a previous location? (Detached head)

If you just want to checkout branch you can simply do:

# checkout the desired branch
git checkout <branch>

If you wish to see all your branches and to checkout one of them:

# Update the repository with the list of all branches and deleted the 
# one who were deleted on the remote
git fetch --all --prune

# List all branches in the repository
git branch -a

How to work on several branches simultaneously?

You work simultaneously on more than one branch with the git worktree command.

From git v2.5

git worktree add <new_path>

git worktree will create 2 separate working folders separated from each other while pointing to the same repository.

This will allow you do to any experintals on the enw worktree without having any effect on the repository itself.

Here is a sample on how to create new worktree and what is the result of it:

enter image description here

Upvotes: 0

Thirumal
Thirumal

Reputation: 9546

After commit and push your local changes.use

git fetch

git pull

git checkout {target branch name }

To merge with master

git merge origin / master

Upvotes: 2

Carlos Parra
Carlos Parra

Reputation: 1067

The HEAD should be in your master branch, and then you have to write:

git merge branch_name

And to go back in your history you should have the hash of the commit you want to go back, and then:

git checkout commit_hash

Here and here you can check the docs for more info.

Upvotes: 0

Related Questions