3

I am fairly new with using git, so I need to push files from master branch to another branch in order to have backup in case something goes wrong and then to continue working on master branch. How do I do that in git bash?

mrmar
  • 1,407
  • 3
  • 11
  • 26
  • 2
    From master, you can checkout to new branch using git checkout -b new-branch so that code in the master will be there in the new-branch. Now again you checkout to your master and continue editing – siva Aug 02 '19 at 07:42
  • 2
    Possible duplicate of [How do I copy a version of a single file from one git branch to another?](https://stackoverflow.com/questions/307579/how-do-i-copy-a-version-of-a-single-file-from-one-git-branch-to-another) – Pavel Anikhouski Aug 02 '19 at 07:43
  • @siva So, something like this. git checkout -b new-branch then push to that new-branch, and then checkout -b old-branch? – mrmar Aug 02 '19 at 07:52
  • 1
    @Marko without the `-b` in the 2nd command because it's an option to create a branch (and it already exists). But IMHO, creating a tag instead of a branch makes more sense. – Philippe Aug 02 '19 at 08:00
  • @Philippe I get error 'fatal: The current branch backup has no upstream branch. ' I – mrmar Aug 02 '19 at 08:13

2 Answers2

7

Git doesn't push files; Git pushes commits. Commits contain files, so the effect is similar, but it's important to keep this in mind: a repository either has a commit (which then has a snapshot of every file), or it doesn't have the commit (and then it does not have those snapshots).

To push the commit(s) you have on your master to some other Git repository—the one you call origin—but have that other repository know them by a name other than (its) master, you can do this:

git push origin master:some-new-branch-name

That sends them—the Git over on origin—any commits that you have, that they don't (but do need). Then it sends them a polite request: Please set your branch named some-new-branch-name so that it remembers the commit I call master.

(Your Git sends them the raw hash ID of this commit, rather than the name master. You can view that raw hash ID, if you like, with:

git rev-parse master

although after you view some raw hash IDs, you'll quickly see why humans don't use them much. Unless you cut-and-paste them they're way too hard to get right.)

After you do the above, if you run:

git fetch origin

you will see that you now have a new remote-tracking name origin/some-new-branch-name. This is your Git's copy of their—origin's—Git's branch name some-new-branch-name. If you run:

git log --all --decorate --oneline --graph

you'll see that not only do you have this new name, but it identifies the very same commit as your own master.

All of this is a little bit silly and/or overkill unless you are concerned that something you do will actually wreck your repository here. The reason is that commits, once made, are permanent—well, mostly permanent—and read-only (totally read-only: nothing in any commit can ever be changed!). The commits themselves are really found by hash ID. A branch name like master just serves as the starting point: your Git translates your name master into a big ugly hash ID, and uses that to find the last commit. That last commit has the big ugly hash ID of its previous or parent commit, so from the last commit, your Git can work backwards one step. The parent commit stores another parent hash ID, so that from the parent, your Git can move backwards another step. That commit has yet another parent ID:

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

Given any commit hash ID, like that for commit H, Git can read the commit and get its parent ID. Then it can read G and get another parent ID, which it can use to read F, and so on. This is what a branch is: It's just a series of commits, strung together backwards by hash IDs, with a branch name pointing to the last one in the series. If H is the last commit, the series looks like this:

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

The name master lets your Git find commit H. That lets your Git find G, then F, and so on.

When you add a new commit to master, what Git is really doing is writing out a new commit (with some new random-looking hash ID) whose parent is commit H. Then Git writes the new commit's hash ID—let's call it I—into the name master, and now you have:

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

When you create a new name, like some-new-branch-name, Git just creates that name, pointing to some existing commit. By default, the new name's commit is the current commit:

...--F--G--H--I   <-- master, some-new-branch-name

This also explains what Git's HEAD is about. If you have more than one branch name, how does Git know which name to update when you make a new commit? The answer is: Git attaches the special name HEAD to one of the branch names. That's the name to be updated when you make new commits. So we really should draw this as:

...--F--G--H--I   <-- master (HEAD), some-new-branch-name

or:

...--F--G--H--I   <-- master, some-new-branch-name (HEAD)

depending on which branch name you selected with git checkout. The current commit is (the real hash ID of) I; the current branch name is whichever name HEAD is attached to.

If you're worried about files, just make a new branch name with git checkout -b, and, if needed, commit (or commit first if you want changes to be added to the other branch first, if that's more appropriate). Your previous branch name now remembers the hash ID of its last commit, and your new branch name remembers the hash ID of any new commits you make:

...--F--G--H--I   <-- master
               \
                J--K   <-- some-new-branch-name (HEAD)

(once you have two commits that are only on the new branch).

(Note that the commits through I are on both branches.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • That's a great answer - do you know how to permanently set the default remote branch for master (for git push --all) , because "push -u" doesn't: git push -u "origin" "master:RELEASE12345" # Does not set it up permanently If there is something to manually edit in .git/config I'm confortable with that. – Malcolm Boekhoff Oct 02 '20 at 01:30
  • That's ... kind of messy. There *is* a way to tell Git to push to the `branch@{upstream}` setting—note that `git push -u ...` is essentially telling Git to run `git branch --set-upstream-to` if the push succeeds—using the `push.default` setting of `upstream`, but this default setting only applies in certain cases. See the (very long) [`git config` documentation](https://git-scm.com/docs/git-config); search for `push.default`. – torek Oct 02 '20 at 03:54
2

First, you need to create a new branch for those backups (but I don't see a need for that because you can go back on any commit you do in the master branch too, but OK).

Creating new branch locally

To create a new branch just use:

git branch <NAME OF NEW BRANCH>

or in this case, we can use

git branch backup

after that, we need to switch to that branch

git checkout <NAME OF NEW BRANCH>

or in this case, we will use

git checkout backup

After that, we need to commit changes

To add all new files (dot replaces all files not currently added to commit)

git add . 

And to do a commit

git commit -m "adding a backup branch"

Then we go to the master branch

git checkout master

and then just push those changes to the git repo

git push origin <feature_branch>

in this case

git push origin backup

Pushing new files from master to backup branch

if you want to have new files as a base in the branch backup, you can use

git rebase master

This will update your base commit in the backup branch. You can read more about rebase here https://git-scm.com/book/de/v2/Git-Branching-Rebasing

OldFart
  • 1,640
  • 11
  • 20
BrunoAFK
  • 116
  • 4