简体   繁体   中英

Git shall we use push or merger to remote master after changes done to local master?

I have clone an android project from git and I have created a local branch called devBranch from master .

I have done many changes in devBranch and I have pushed it remotely as well.

Now once I've finished with all the changes in devBranch I have merged those changes to the master local branch.

Now I want to push those new changes in local master to remote master.

What is the appropriate approach? shall I use push or merge and why?

Comparing git push to git merge is not very sensible:

  • The git push command is about sending some commit(s) to some other Git that is in charge of some other repository, so that the other repository gets the new commit(s), then asking that other Git to adjust some branch and/or other names in that other repository.

  • The git merge command is complicated, but when used in one of its typical ways, is about making a new commit in the current branch of your own repository. This new commit is typically a merge commit , with two parents, instead of the more common ordinary commit with one parent.

Now, there are occasions where git merge doesn't make a new commit, and instead performs a fast-forward operation . A fast-forward operation is a change in a branch name such that the new commit hash ID stored in that name identifies a descendant of the commit whose hash ID was previously stored in that name. (That's a pretty jargon-heavy statement that requires a bit of graph theory to understand. See below for a simple example.)

The git push command can also be used to send no new commits, yet still request that the other Git repository make a change to one of its branch names. This change can be a fast-forward operation, whether or not your Git sends over any new commits. In fact, if the branch-name change is a non-fast-forward operation, the git push command needs the --force or --force-with-lease option.

Since both git merge and git push can engage in this kind of fast-forward action, there is at least one case where the two are somewhat comparable. The key difference for this particular case, though, is that git merge performs the fast-forward in your repository, and git push performs the fast-forward in some other Git repository.

The bottom line, as it were, is simple enough:

  • If you need to make a merge commit, you must do that locally. The git push command cannot do that.
  • If you don't need to make a merge commit, ask yourself whose branch name(s) need what kind of update(s). To update your own branch names, work locally. To update some other Git repository , use git push .

Remember that repositories share commits (by hash IDs), but have their own private branch names . Your names are not anyone else's names, and need not be used the same way—but with humans being humans, we tend to use the same names the same way, because it's too confusing if I call you Fred and your co-workers call you Piotr when your name is actually Rahul.

Drawing what it means to do a fast-forward

To understand Git's notion of fast-forwards, let's start with the fact that branch names hold commit hash IDs, and commits also hold commit hash IDs. Whenever something holds a commit hash ID, we say that that something—whatever it is— points to that commit. So a commit points to another commit, and a branch name points to a commit.

The actual name of any given commit is some big ugly hash ID, like faefdd61ec7c7f6f3c8c9907891465ac9a2a1475 for instance. These are too annoying to type in, and too tricky for humans to remember, so let's draw our own Git commit graph fragments using uppercase letters to stand in for each commit. Here, we have three commits in a row, with the last (latest) one being commit H :

... <-F <-G <-H

Since H is the latest commit, we'll have a branch name point to it:

... <-F <-G <-H   <--master

Meanwhile, commit H itself actually stores the raw (and real) hash ID of earlier commit G . So H points to G . Commit G , in turn, stores inside it the hash ID of yet-earlier commit F : G points to F . This is what we have drawn here.

No part of any commit, once it is made, can ever be changed. This means we don't really have to draw the internal, backwards-pointing, arrows between commits as arrows: we can just draw them as connecting lines. This is useful when we start adding more commits beyond H , using another name to find them:

...--F--G--H   <-- master
            \
             I--J   <-- dev

Here, the branch name dev points to commit J , which points backwards to commit I , which points backwards to commit H , and so on. Meanwhile the name master still points to existing commit H .

We can now ask Git to "slide the name master forward". If we move forward just one commit, master ends up pointing to I , like this:

...--F--G--H--I   <-- master
               \
                J   <-- dev

Note how the commits have not changed: we've just drawn commit I one row higher because there's no other good way to draw them on StackOverflow. The names changed, or more precisely, the values stored in the name master changed, so that master now points to I .

If we slide master all the way forward, we get:

...--F--G--H
            \
             I--J   <-- dev, master

and there's now no reason to keep drawing in the kink at all:

...--H--I--J   <-- dev, master

suffices.

This operation—moving master "forward" one or more commits—is what Git calls a fast forward , because even though master now points to I or J , we can, by starting at whatever commit we find now through that name, work our way backwards to where master was before. It was at commit H , and J points to I which points to H . So commit H remains on the branch named master .

But what if we start with this:

...--F--G   <-- master

then add a new name dev also pointing to existing commit G :

...--F--G   <-- dev, master

and then make one new commit on master , so that it points to this new commit H , but then check out branch dev and make one new commit on dev , so that dev points to new commit I ? We will now have:

          H   <-- master
         /
...--F--G
         \
          I   <-- dev

From master (which locates commit H ), we can work our way back to commit G , then commit F , and so on. From dev —commit I —we can work back to G and F and so on as well. But these arrows that connect commits are exclusively backwards arrows. We cannot go "forwards" from G to H . Git's connections only point backwards . We need the name master so as to find commit H , before we go back.

If we force Git to move the name master to point to commit I , we end up with:

          H   ???
         /
...--F--G
         \
          I   <-- dev, master

The commit still exists, but we have no way to find its hash ID. Commit H is lost: it's still there (for a while) but unless we force Git to recover it reasonably quickly, Git will eventually remove it entirely as unnecessary. 1 This kind of forced name motion, where commit H is lost, is a non-fast-forward .

If we'd like to join commits H and I and keep the work done in both, we'll need to use git merge (or something similar).


1 In a normal repository, Git leaves traces that will let us recover the commit for at least another 30 days. In a bare repository on a server, the recovery time is much shorter.

The appropriate approach is to do a git push

Why? Because you have a remote and you want to save your current working state to that remote repository. A remote simply helps you save your different commits and current working state. This serves two good purposes: 1. You are able to collaborate with other team members using the same remote and 2. You can access your repository anywhere even without your local machine.

git merge creates a unified branch of the two branches merged. If you do a git merge the files you have on your remote will be merged with your current working files on your local machine. a git merge gets more complicated and mainly works on files on your local machine

Udacity has a free good course on the basics of git and git hub

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