Rebasing and what does one mean by rebasing pushed commits
It is often said that, you should not reba开发者_StackOverflow中文版se commits that you have already pushed. What could be meaning of that?
To understand this, we need to understand a bit about how git works. A git repository is a tree structure, where the nodes of the tree are commits. Here's an example of a very simple repository:
it has four commits on the master branch, and each commit has an ID (in this case, a, b, c, and d). You'll notice that d is currently the latest commit (or HEAD) of the master branch.
Here, we have two branches: master and my-branch. You can see that master and my-branch both contain commits a and b, but then they start to diverge: master contains c and d, while my-branch contains e and f. b is said to be the "merge base" of my-branch in comparison to master -- or more commonly, just the "base". It makes sense: you can see that my-branch was based on a previous version of master.
So let's say that my-branch has gone stale, and you want to bring it up to date with the latest version of master. To put it another way, my-branch needs to contain c and d. You could do a merge, but that causes the branch to contain weird merge commits that make reviewing the pull request much more difficult. Instead, you can do a rebase.
When you rebase, git finds the base of your branch (in this case, b), finds all the commits between that base and HEAD (in this case, e and f), and re-plays those commits on the HEAD of the branch you're rebasing onto (in this case, master). Git actually creates new commits that represent what your changes look like on top of master: in the diagram, these commits are called e′ and f′. Git doesn't erase your previous commits: e and f are left untouched, and if something goes wrong with the rebase, you can go right back to the way things used to be.
When many different people are working on a project simulateously, pull requests can go stale quickly. A "stale" pull request is one that is no longer up to date with the main line of development, and it needs to be updated before it can be merged into the project. The most common reason why pull requests go stale is due to conflicts: if two pull requests both modify similar lines in the same file, and one pull request gets merged, the unmerged pull request will now have a conflict. Sometimes, a pull request can go stale without conflicts: perhaps changes in a different file in the codebase require corresponding changes in your pull request to conform to the new architecture, or perhaps the branch was created when someone had accidentally merged failing unit tests to the master branch. Regardless of the reason, if your pull request has gone stale, you will need to rebase your branch onto the latest version of the master branch before it can be merged.
The ProGit book has a good explanation.
The specific answer to your question can be found in the section titled "The Perils of Rebasing". A quote from that section:
When you rebase stuff, you’re abandoning existing commits and creating new ones that are similar but different. If you push commits somewhere and others pull them down and base work on them, and then you rewrite those commits with git rebase and push them up again, your collaborators will have to re-merge their work and things will get messy when you try to pull their work back into yours.
Update:
Based on your comment below, it sounds like your are having difficulty with your Git workflow. Here are some references that may help:
- The
gitworkflows
man page: See "Merging Upwards" and "Topic Branches" - ProGit: See "Private Managed Team"
- Jarrod Spillers blog: See "git merge vs git rebase: Avoiding Rebase Hell"
Rebasing rewrites history. If nobody knows about that history, then that is perfectly fine. If, however, that history is publicly known, then rewriting history in Git works just the way it does in the real world: you need a conspiracy.
Conspiracies are really hard keep together, so you better avoid rebasing public branches in the first place.
Note that there are examples of successful conspiracies: the pu
branch of Junio C. Hamano's git repository (the official repository of the Git SCM) is rebased frequently. The way that this works is that pretty much everybody who uses pu
is also subscribed to the Git developer mailinglist, and the fact that the pu
branch is rebased is widely publicized on the mailinglist and the Git website.
A rebase alters the history of your repository. If you push commits out to the world, i.e., make them available to others, and then you change your view of the commit history, it becomes difficult to work with anyone who has your old history.
Rebase considered harmful is a good overview, I think.
精彩评论