How to create a function branch and reset to the beginning / master in one operation?

I often begin my journey with a small fix on the lead branch, which in the end seems more complicated than originally intended.

Therefore, I easily fall into this situation:

* Damned I have more stuff to check (HEAD -> master) * Forgot to fix this as well... * Oops, fixed that too * Fixed this * (origin/master) 

And at that moment someone asks me to quickly make a small change on the main branch. Therefore, I need to create a feature / bugfix and return master to its origin :

 $ git branch --magic bug/foobar $ git log * Damned I have more stuff to check (HEAD -> bug/foobar) * Forgot to fix this as well... * Oops, fixed that too * Fixed this * (master, origin/master) 

I am currently solving my problem as follows:

 $ git branch bug/foobar $ git reset --hard origin/master $ git checkout bug/foobar 

I can obviously create an alias for it (not yet verified):

 swap-to="!git branch $@ && \ git reset --hard \ \$(git config --get branch.\$(git rev-parse --abbrev-ref HEAD).remote)/\ \$(git rev-parse --abbrev-ref HEAD) && \ git checkout $@ " 

Is there a faster / smarter way to do this?

+5
source share
3 answers

Reinstalling the problem

Here you start work with master , but we can choose any start (local) branch B that has some upstream U installation. (In your particular case, the origin/master upstream.) You started with a task that you think , was quick and easy, and now you realized that it is not so fast and easy in the end, so you would like to "twist" turn it off "in your thread.

Thus, we can notice that we want to save the name of the current branch, and then change Git the concept of “current branch” to a newly created branch, indicating the current commit, and then adjust the saved branch to point to the saved branch upstream.

Background

The names of the branches are just labels indicating some commit. Git is reasonable enough here: git branch allows you to create a new label that points to any existing commit, or move anything other than the current branch to any existing commit. By default, a new branch is created that points to the current commit.

The tricky part is that the current branch cannot be moved this way, and the reason for this is that the current branch must match the index and the work tree, except for any active changes that you are currently making. There is only one user ("china") command to change the Git concept of the "current branch", which is git checkout .

Fortunately, git checkout also has the -b flag (create new branch), which works the same as git branch : by default, it creates a new branch at the current commit. In addition, he avoids touching the index and the tree as much as possible - like any other git checkout - so if we create a new branch with the current commit, she will never have to touch the index or the work tree at all. As a result, he always succeeds and leaves us on a newly created branch. (He can create a new branch that points to a specific commit, but it can also fail, but we don’t need this function here, so we can use a mode in which it does not fail. Fail "until the new name branches really is new, at least.)

Therefore, the solution

The solution still should be a few lines of script, but we can write this as a small script called git-spinoff and put it in our $ PATH (I would use $HOME/scripts/git-spinoff for this). We could do this as a function of a shell alias, but I think scripts are better at all (easier to understand, debug, etc.).

To make this script reliable, let's actually check our prerequisite: we are on some branch (therefore HEAD not "disconnected") and that this branch has an upstream set. Then we can create our new branch and use the git branch -f redirect points, i.e. Without using git reset , another branch:

 #! /bin/sh # # git-spinoff: spin the current branch off to a new # branch. When this succeeds, we are on the new branch. die() { echo "fatal: $@ " 1>&2 exit 1 } # check arguments case $# in 1) newbranch="$1";; *) echo "usage: git spinoff <newbranch>" 1>&2; exit 1;; esac # make sure we are on a branch that has an upstream branch=$(git symbolic-ref -q --short HEAD) || die "existing branch is detached; there nothing to restore" upstream=$(git rev-parse -q --verify @{u}) || die "existing branch $branch has no upstream: there nowhere to restore-to" # now create and check out out the new branch, or quit if we can't git checkout -b "$newbranch" || exit $? # last, re-adjust the previous branch (which is no longer the current # branch since we are on the new one we created) to point to its own # upstream (if this fails, ignore the failure!) git branch -f "$branch" "$upstream" 

This last team can really be improved, as there is a “plumbing team” that does what we want. To use it, we must save the full ( refs/heads/ style) name of the source branch and select the message. This particular post can be improved, therefore, this is just a sample:

 fullbranch=$(git symbolic-ref -q HEAD) || die ... branch=${fullbranch#refs/heads/} ... same as before ... git update-ref -m \ "git spinoff: re-point $branch to ${branch}@{upstream}" \ $fullbranch $upstream 

With this git-spinoff script in our way, we can now run git spinoff .

Edit: this is now verified and included in https://github.com/chris3torek/scripts (as https://github.com/chris3torek/scripts/blob/master/git-spinoff ).

+2
source

As far as I know, the only way to achieve this is in only one operation, as you said, using an alias, but for performing several operations I personally prefer the alias to bash functions, basically the same as alias (you declare them in a single file), but they look cleaner and more vulnerable. For instance:

 yourFunction() { command1 command2 . . . } 

Hope this helps.

+1
source

You should be able to just check the main branch as a new branch

  $ git checkout origin/master -b feature/new_featur 

Edit

The above solution, while it works, sets up a new branch to track the main branch. (What I do not like)

I usually do not check before proceeding.

I watched IntelliJ check out a new branch, and here's how.

 $ git checkout origin/master 

After that, git will tell you that you are on a separate head. Now that you have a HEAD that matches origin/master , go and check that commit is like a new branch.

 $ git checkout -b feature/new_feature 

DON'T FORGET before git fetch

:) Magic wound, huh? I hope this helps!

+1
source

Source: https://habr.com/ru/post/1260334/


All Articles