Merge, update, and pull Git branches without using checkouts

前端 未结 17 1413
臣服心动
臣服心动 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条回答
  •  -上瘾入骨i
    2020-11-22 08:21

    The Short Answer

    As long as you're doing a fast-forward merge, then you can simply use

    git fetch  :
    

    Examples:

    # Merge local branch foo into local branch master,
    # without having to checkout master first.
    # Here `.` means to use the local repository as the "remote":
    git fetch . foo:master
    
    # Merge remote branch origin/foo into local branch foo,
    # without having to checkout foo first:
    git fetch origin foo:foo
    

    While Amber's answer will also work in fast-forward cases, using git fetch in this way instead is a little safer than just force-moving the branch reference, since git fetch will automatically prevent accidental non-fast-forwards as long as you don't use + in the refspec.

    The Long Answer

    You cannot merge a branch B into branch A without checking out A first if it would result in a non-fast-forward merge. This is because a working copy is needed to resolve any potential conflicts.

    However, in the case of fast-forward merges, this is possible, because such merges can never result in conflicts, by definition. To do this without checking out a branch first, you can use git fetch with a refspec.

    Here's an example of updating master (disallowing non-fast-forward changes) if you have another branch feature checked out:

    git fetch upstream master:master
    

    This use-case is so common, that you'll probably want to make an alias for it in your git configuration file, like this one:

    [alias]
        sync = !sh -c 'git checkout --quiet HEAD; git fetch upstream master:master; git checkout --quiet -'
    

    What this alias does is the following:

    1. git checkout HEAD: this puts your working copy into a detached-head state. This is useful if you want to update master while you happen to have it checked-out. I think it was necessary to do with because otherwise the branch reference for master won't move, but I don't remember if that's really right off-the-top of my head.

    2. git fetch upstream master:master: this fast-forwards your local master to the same place as upstream/master.

    3. git checkout - checks out your previously checked-out branch (that's what the - does in this case).

    The syntax of git fetch for (non-)fast-forward merges

    If you want the fetch command to fail if the update is non-fast-forward, then you simply use a refspec of the form

    git fetch  :
    

    If you want to allow non-fast-forward updates, then you add a + to the front of the refspec:

    git fetch  +:
    

    Note that you can pass your local repo as the "remote" parameter using .:

    git fetch . :
    

    The Documentation

    From the git fetch documentation that explains this syntax (emphasis mine):

    The format of a parameter is an optional plus +, followed by the source ref , followed by a colon :, followed by the destination ref .

    The remote ref that matches is fetched, and if is not empty string, the local ref that matches it is fast-forwarded using . If the optional plus + is used, the local ref is updated even if it does not result in a fast-forward update.

    See Also

    1. Git checkout and merge without touching working tree

    2. Merging without changing the working directory

提交回复
热议问题