0

I am trying to publish a newer version of my NPM package. The previous version and the current version doesn't have much similarities. We want to override the branch but don't want to lose it's history. How can we accomplish this?

Aditya Jamuar
  • 117
  • 1
  • 10
  • 2
    What do you mean by "override the branch"? What is the current state of your git history? What do you want the end state to be? – Code-Apprentice Jun 22 '21 at 16:11
  • I want the branch from the previous version to have the code of the latest one. But I also want to preserve the history. – Aditya Jamuar Jun 28 '21 at 09:08
  • 1
    This sounds like a fundamental misunderstanding about what Git does. torek's answer below gives a good explanation. That should help clear up that misunderstanding. I also recommend the book Pro Git which you can get for free online (google it). – Code-Apprentice Jun 28 '21 at 17:09

3 Answers3

2

History, in any Git repository, is simply the set of commits in the repository. Each commit is numbered, with a big ugly hash ID. Run git log, supply it with a raw commit hash ID, and Git will show you:

  • that commit; then
  • that commit's parent commit (the commit that that commit was made from); then
  • the grand-parent commit; then
  • the great-grand-parent commit;

and so on. That "family tree" of commits is the history.

A branch name, in Git, is simply a way to record one particular commit hash ID, so that you do not have to memorize the big ugly random-looking hash ID of that particular commit. Tag names serve the same purpose: they store the hash ID of one particular commit. The key difference between a branch name and a tag name is that a branch name is designed to move, and in fact, will move automatically, by you checking out the branch, then making a new commit.

When you are on branch B and make a new commit, the new commit's parent commit is, automatically, whatever commit B used to name. The new commit is then the commit that branch B names.

What this means is that if you want the "history" starting from B, and working backwards through the family tree, to include the previous commits that were on B, you must make the new commit come after the currently-last commit on B.

Meanwhile, note that each commit—each big ugly random-looking hash ID—not only represents the history starting from that point and working backwards. It also stores a full snapshot of every file. When you use git log -p to see changes, what you see is the result of Git comparing adjacent snapshots: between this commit's parent, and this commit, the snapshots changed in this way.

Should you wish one particular new commit to store, as its full snapshot, the same snapshot that some other existing commit has, but have as its parent, the same commit that some particular branch name already stores, this is easy to achieve. There are multiple ways to do it. It is, however, a very unusual thing to want.

Should you wish to keep all the commits you have now starting from some branch named B and working backwards, but use some other name for these commits, you can simply change the name. Branch names are not set in stone: any branch can be renamed at any time.

One thing to be careful about here, though, is that every Git repository has its own branch names. These names are not shared at all. When you clone a repository, you get all of the other repository's commits, and none of its branches. Your Git then creates one new branch name in your clone, so that you have one actual branch name. Your Git finds the other commits—the ones that findable by a branch name—using your remote-tracking names, such as origin/master or origin/main, origin/develop, and so on. These names exist because your Git created them by renaming the other Git's branch names. Each time your Git reaches out to the original (origin) Git to get updates, your Git will create or update your own remote-tracking names to correspond to any updates they made to their branch names.

What all of this means is that if you change the branch name in some repository, the remote-tracking names in clones of that repository will change—but the branch names in clones of that repository won't. Each user will need to do their own branch-name renaming, if they are using that branch name.

Hence, renaming the branch is a fine thing to do, but you must tell all your users / co-workers about this change, so that they can make the same change to their Git if they choose. (They don't have to do that—there's no reason they can't use the name zorg instead of develop, for instance—but most people do like to have their own branch names match some other Git's branch names, so that their zorg matches their origin/zorg, not their origin/develop.)

See also Making two branches identical, How to make branch B exactly like branch A?, git command for making one branch like another, How do I 'overwrite', rather than 'merge', a branch on another branch in Git?, and many other instances of this general kind of question.

torek
  • 448,244
  • 59
  • 642
  • 775
1

I think you can just create a new branch a part of your last branch or hash (of course, of your last branch).

git checkout old-branch
git checkout -b new-branch
0

In addition to torek's great answer, I want to mention that the question appears to indicate a fundamental misunderstanding of what Git does. Versions should have tags, not branches, once they are released. A version branch can be helpful to prepare for a release but should be merged into the trunk branch and tagged.

Additionally, a tag for a new release should include the history of all previous releases. If Git is used correctly, this just happens automatically. However, a tag for an old release should know nothing about the history of an newer releases. This is the point of "history". It only gives you a view into the past, not the future.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268