Going to a branch that is not verified

I use git to version my home directories on several different machines. I would like each of them to use separate branches, and they exit from the general branch. Thus, most commits should be made for this general branch, unless something specific for this machine is being executed, in which case the commit should go to a verified branch, depending on the machine. In this case, the switch branches are clearly not very good.

He mentioned in this post that what I want to do is impossible, but I found that the answer was rather dumb and might not have considered the possibility of using plumbing commands. Unfortunately, I do not have enough reputation to comment on this topic. I rather suspect that there is some way to do this, and I was hoping to save an hour or more in finding the answer by simply asking you for good people.

So, is it possible to commit another branch without checking it first? Ideally, I would like to use the index in the same way as usual git commit .

+4
source share
3 answers

I believe that the best way to do what you want is to make your commits on top of a machine-specific branch, then move them using git to rebase . This is roughly what I am doing with my own home directory - essentially the same situation as yours.

 # make a new branch starting from branch machine_1 git checkout -b move_to_master # make whatever commits you need to git rebase --onto master machine_1 move_to_master git checkout master git merge move_to_master # this is a fast-forward git checkout machine_1 git merge master 

If you accidentally transfer machine_1 before creating move_to_master, just create move_to_master, then reset machine_1 back to where it belongs, and follow the rest of the steps.

However, your question is worth answering, and I have provided a couple of alternatives below.

Creating commits not for the current branch

Precautions: Be very careful! This is scary!

You can fix a branch that is not checked by plumbing teams, just not necessarily very desirable. You should get your index in the state you need (it can be difficult), and then you can use git commit-tree :

 git commit-tree -p $PARENT_COMMIT < $COMMIT_MESSAGE_FILE 

This will print to display the newly created commit object on the SHA1 screen; if PARENT_COMMIT was the end of a branch, you should use git update-ref to update the branch to it:

 git update-ref -m "commit: [commit subject]" $BRANCH $NEW_SHA1 

If you create a script, you can achieve it in one layer as git update-ref -m ... $(git commit tree ...) . This is the worst step. If you update - return another branch to the wrong place, this sucks. You can still determine where to reset back with git reflog show $BRANCH .

In any case, it was just the easy part. The most difficult thing is to get the index in the state you need without checking the files. Two common commands you can use:

  • git read-tree - reads information about trees into the index, but does not update the work tree at all (git checking is roughly equivalent to git read-tree, git checkout-index and git update-ref HEAD). You can use this so that the index contains the contents of this unfinished branch instead of HEAD.
  • git update-index - changes the index. You can use this to add, delete or update files in the index from the work tree.
  • git checkout-index - copy the given paths from the index to the work tree. After using read-tree, you can use this to get the individual file you want to modify, modify it, and then return it using the update index. The step of “changing it” can be complicated - for example, before doing all this, you can create a patch using git diff and then apply it using git here.
  • git apply --cached Using the -cached option applies the patch directly to the version in the index without touching the work tree. Therefore, you can create diff, read-tree in another branch, apply it to the index, commit-tree and install. This is probably the most amazing way to do this.

The reason that all this is so complicated is that all the git commands that give you access to all of their powerful merge capabilities are dependent on the availability of files in the work tree. When you think about it, the task you are trying to do is merge - you have a difference in one branch, and you want to apply it to another. The way to get the result is to do a three-way merge using diff on the source branch, a common ancestor with another branch, and the tip of another branch. If you do not check another branch, you cannot merge it!

As usual, when you do things with the help of plumbing teams, you must be very careful to understand how everything works so that you do not terribly ruin your repository. However, I really used this with great effect when restructuring existing repositories (created by others ... don't ask). I only rewrote the commits in these cases - using read-tree and usually update-index, so it was much simpler than you are probably trying to do.

Alternative approaches

Having said all this, there are a few more approaches you could take to do what you want.

  • clone your repository. If you only keep track of configuration files, it will not take up much space, and everything will be much simpler. If you are really obsessive, you can even use the git new-workdir (version link in HEAD git.git) script to make only the working directory and not duplicate the rest of the repo (it uses symbolic links in the .git directory). Just remember, to be careful in completing a branch in one workdir that checked in another - the other will end up with a processing tree that is not synchronized.

  • writing a wrapper with one commit script is the closest thing to making one commit for another branch of all these options:

     git commit orig_branch=$(git symbolic-ref HEAD) orig_branch=${orig_branch#refs/heads/} git checkout master git cherry-pick $orig_branch git checkout $orig_branch git reset --hard HEAD^ 
+12
source

I am doing this for my Visual Git Reference project. I run make gh-pages , which creates a website and passes it to the gh-pages branch, without having to switch branches. See My GitHub repo , in particular Makefiles and publication. I probably should use $GIT_INDEX_FILE as the above mentioned Chris Johnsen, but it seems to work fine.

+1
source

I may have misinterpreted your request, but let me know if this is what you are looking for.

You start work in a separate branch of the machine. You are making changes, but instead of moving to a machine-specific branch, you want to commit the change to the general branch. What you have to do is

 git stash # save your changes for later git checkout common # switch to the common branch git stash apply # recall the stashed changes git commit # commit as appropriate (on the common branch) git stash drop # kill off the last stashed changes (this is optional) git checkout machine1 # go to your machine-specific branch git rebase common # put your machine-specific changes after the common ones git checkout machine2 # [repeat] git rebase common 

Alternatively, you can use git merge instead of git rebase if this is not the way your changes might apply.

Does this apply to your situation?

0
source

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


All Articles