Merge, update, and pull Git branches without using checkouts

前端 未结 17 1374
臣服心动
臣服心动 2020-11-22 07:42

I work on a project that has 2 branches, A and B. I typically work on branch A, and merge stuff from branch B. For the merging, I would typically do:

git mer         


        
相关标签:
17条回答
  • 2020-11-22 08:32

    You can clone the repo and do the merge in the new repo. On the same filesystem, this will hardlink rather than copy most of the data. Finish by pulling the results into the original repo.

    0 讨论(0)
  • 2020-11-22 08:33
    git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]
    

    You can try git worktree to have two branches open side by side, this sounds like it might be what you want but very different than some of the other answers I've seen here.

    In this way you can have two separate branches tracking in the same git repo so you only have to fetch once to get updates in both work trees (rather than having to git clone twice and git pull on each)

    Worktree will create a new working directory for your code where you can have a different branch checked out simultaneously instead of swapping branches in place.

    When you want to remove it you can clean up with

    git worktree remove [-f] <worktree>
    
    0 讨论(0)
  • 2020-11-22 08:34

    The question is simple and the answer should be as simple. All the OP is asking is to merge the upstream origin/branchB into his current branch without switching branches.

    TL;DR:

    git fetch
    git merge origin/branchB
    

    The full answer:

    git pull does a fetch + merge. It's roughly the the same the two commands below, where <remote> is usually origin (default), and the remote tracking branch starts with <remote>/ followed by the remote branch name:

    git fetch [<remote>]
    git merge @{u}
    

    The @{u} notation is the configured remote tracking branch for the current branch. If branchB tracks origin/branchB then @{u} from branchB is the same as typing origin/branchB (see git rev-parse --help for more info).

    Since you already merge with origin/branchB, all that is missing is the git fetch (which can run from any branch) to update that remote-tracking branch.

    Note though that if there was any merge from the pull to include, you should rather merge branchB into branchA after having done a pull from branchB (and eventually push the changes to orign/branchB), but as long as they're fast-forward they would remain the same.

    Keep in mind the local branchB will not be updated until you switch to it and do an actual pull, however as long as there are no local commits added to this branch it will just remain a fast-forward to the remote branch.

    0 讨论(0)
  • 2020-11-22 08:36

    No, there is not. A checkout of the target branch is necessary to allow you to resolve conflicts, among other things (if Git is unable to automatically merge them).

    However, if the merge is one that would be fast-forward, you don't need to check out the target branch, because you don't actually need to merge anything - all you have to do is update the branch to point to the new head ref. You can do this with git branch -f:

    git branch -f branch-b branch-a
    

    Will update branch-b to point to the head of branch-a.

    The -f option stands for --force, which means you must be careful when using it.

    Don't use it unless you are absolutely sure the merge will be fast-forward.

    0 讨论(0)
  • 2020-11-22 08:36

    I wrote a shell function for a similar use case I encounter daily on projects. This is basically a shortcut for keeping local branches up to date with a common branch like develop before opening a PR, etc.

    Posting this even though you don't want to use checkout, in case others don't mind that constraint.

    glmh ("git pull and merge here") will automatically checkout branchB, pull the latest, re-checkout branchA, and merge branchB.

    Doesn't address the need to keep a local copy of branchA, but could easily be modified to do so by adding a step before checking out branchB. Something like...

    git branch ${branchA}-no-branchB ${branchA}
    

    For simple fast-forward merges, this skips to the commit message prompt.

    For non fast-forward merges, this places your branch in the conflict resolution state (you likely need to intervene).

    To setup, add to .bashrc or .zshrc, etc:

    glmh() {
        branchB=$1
        [ $# -eq 0 ] && { branchB="develop" }
        branchA="$(git branch | grep '*' | sed 's/* //g')"
        git checkout ${branchB} && git pull
        git checkout ${branchA} && git merge ${branchB} 
    }
    

    Usage:

    # No argument given, will assume "develop"
    > glmh
    
    # Pass an argument to pull and merge a specific branch
    > glmh your-other-branch
    

    Note: This is not robust enough to hand-off of args beyond branch name to git merge

    0 讨论(0)
提交回复
热议问题