Improve `hub merge` to not generate leftover remote refs

The previous implementation fetched refs into `refs/remotes/OWNER/BRANCH`.
Now, fetch `refs/pull/ID/head` directly into FETCH_HEAD and merge that.
It's a more straightforward approach that generates no artefacts.

This is for similarity with the reimplemented `hub checkout` command
which now also uses `refs/pull/ID/head`.
This commit is contained in:
Mislav Marohnić 2016-09-14 02:41:58 +02:00
Родитель b972284fba
Коммит cbf7ab1ba3
3 изменённых файлов: 55 добавлений и 111 удалений

Просмотреть файл

@ -61,23 +61,30 @@ func transformMergeArgs(args *Args) error {
return err
}
repo, err := github.LocalRepo()
if err != nil {
return err
}
remote, err := repo.RemoteForRepo(pullRequest.Base.Repo)
if err != nil {
return err
}
branch := pullRequest.Head.Ref
headRepo := pullRequest.Head.Repo
if headRepo == nil {
return fmt.Errorf("Error: that fork is not available anymore")
}
u := url.GitURL(headRepo.Name, headRepo.Owner.Login, headRepo.Private)
mergeHead := fmt.Sprintf("%s/%s", headRepo.Owner.Login, branch)
ref := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s", branch, mergeHead)
args.Before("git", "fetch", u, ref)
args.Before("git", "fetch", remote.Name, fmt.Sprintf("refs/pull/%s/head", id))
// Remove pull request URL
idx := args.IndexOfParam(mergeURL)
args.RemoveParam(idx)
mergeMsg := fmt.Sprintf("Merge pull request #%v from %s\n\n%s", id, mergeHead, pullRequest.Title)
args.AppendParams(mergeHead, "-m", mergeMsg)
mergeMsg := fmt.Sprintf("Merge pull request #%s from %s/%s\n\n%s", id, headRepo.Owner.Login, branch, pullRequest.Title)
args.AppendParams("FETCH_HEAD", "-m", mergeMsg)
if args.IndexOfParam("--ff-only") == -1 && args.IndexOfParam("--squash") == -1 && args.IndexOfParam("--ff") == -1 {
i := args.IndexOfParam("-m")

Просмотреть файл

@ -4,10 +4,21 @@ Feature: hub merge
And the "origin" remote has url "git://github.com/defunkt/hub.git"
And I am "mislav" on github.com with OAuth token "OTOKEN"
Scenario: Normal merge
When I run `hub merge master`
Then the git command should be unchanged
Scenario: Merge pull request
Given the GitHub API server:
"""
get('/repos/defunkt/hub/pulls/164') { json \
:base => {
:repo => {
:owner => { :login => "defunkt" },
:name => "hub",
:private => false
}
},
:head => {
:ref => "hub_merge",
:repo => {
@ -19,10 +30,10 @@ Feature: hub merge
:title => "Add `hub merge` command"
}
"""
And there is a commit named "jfirebaugh/hub_merge"
And there is a git FETCH_HEAD
When I successfully run `hub merge https://github.com/defunkt/hub/pull/164`
Then "git fetch git://github.com/jfirebaugh/hub.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
And "git merge jfirebaugh/hub_merge --no-ff -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
Then "git fetch origin refs/pull/164/head" should be run
And "git merge FETCH_HEAD --no-ff -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
When I successfully run `git show -s --format=%B`
Then the output should contain:
"""
@ -31,11 +42,18 @@ Feature: hub merge
Add `hub merge` command
"""
Scenario: Merge pull request with --ff-only option
Scenario: Merge pull request with options
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:base => {
:repo => {
:owner => { :login => "defunkt" },
:name => "hub",
:private => false
}
},
:head => {
:ref => "hub_merge",
:repo => {
@ -47,97 +65,28 @@ Feature: hub merge
:title => "Add `hub merge` command"
}
"""
And there is a commit named "jfirebaugh/hub_merge"
When I successfully run `hub merge --ff-only https://github.com/defunkt/hub/pull/164`
Then "git fetch git://github.com/jfirebaugh/hub.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
And "git merge --ff-only jfirebaugh/hub_merge -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
When I successfully run `git show -s --format=%B`
Then the output should contain:
"""
Fast-forward (no commit created; -m option ignored)
"""
And there is a git FETCH_HEAD
When I successfully run `hub merge --squash https://github.com/defunkt/hub/pull/164 --no-edit`
Then "git fetch origin refs/pull/164/head" should be run
And "git merge --squash --no-edit FETCH_HEAD -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
Scenario: Merge pull request with --squash option
Scenario: Merge pull request no repo
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:head => {
:ref => "hub_merge",
:base => {
:repo => {
:owner => { :login => "jfirebaugh" },
:owner => { :login => "defunkt" },
:name => "hub",
:private => false
}
},
:title => "Add `hub merge` command"
}
"""
And there is a commit named "jfirebaugh/hub_merge"
When I successfully run `hub merge --squash https://github.com/defunkt/hub/pull/164`
Then "git fetch git://github.com/jfirebaugh/hub.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
And "git merge --squash jfirebaugh/hub_merge -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
When I successfully run `git show -s --format=%B`
Then the output should contain:
"""
Fast-forward (no commit created; -m option ignored)
"""
Scenario: Merge pull request with --ff option
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:head => {
:ref => "hub_merge",
:repo => {
:owner => { :login => "jfirebaugh" },
:name => "hub",
:private => false
}
},
:title => "Add `hub merge` command"
}
"""
And there is a commit named "jfirebaugh/hub_merge"
When I successfully run `hub merge --ff https://github.com/defunkt/hub/pull/164`
Then "git fetch git://github.com/jfirebaugh/hub.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
And "git merge --ff jfirebaugh/hub_merge -m Merge pull request #164 from jfirebaugh/hub_merge" should be run
When I successfully run `git show -s --format=%B`
Then the output should contain:
"""
Fast-forward (no commit created; -m option ignored)
"""
Scenario: Merge private pull request
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:head => {
:ref => "hub_merge",
:repo => {
:owner => { :login => "jfirebaugh" },
:name => "hub",
:private => true
}
},
:title => "Add `hub merge` command"
}
"""
And there is a commit named "jfirebaugh/hub_merge"
When I successfully run `hub merge https://github.com/defunkt/hub/pull/164`
Then "git fetch git@github.com:jfirebaugh/hub.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
Scenario: Missing repo
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:head => {
:ref => "hub_merge",
:repo => nil
}
},
:title => "Add `hub merge` command"
}
"""
When I run `hub merge https://github.com/defunkt/hub/pull/164`
@ -146,26 +95,3 @@ Feature: hub merge
"""
Error: that fork is not available anymore\n
"""
Scenario: Renamed repo
Given the GitHub API server:
"""
require 'json'
get('/repos/defunkt/hub/pulls/164') { json \
:head => {
:ref => "hub_merge",
:repo => {
:owner => { :login => "jfirebaugh" },
:name => "hub-1",
:private => false
}
}
}
"""
And there is a commit named "jfirebaugh/hub_merge"
When I successfully run `hub merge https://github.com/defunkt/hub/pull/164`
Then "git fetch git://github.com/jfirebaugh/hub-1.git +refs/heads/hub_merge:refs/remotes/jfirebaugh/hub_merge" should be run
Scenario: Unchanged merge
When I run `hub merge master`
Then "git merge master" should be run

Просмотреть файл

@ -82,6 +82,17 @@ Given(/^there is a commit named "([^"]+)"$/) do |name|
run_silent %(git reset --quiet --hard HEAD^)
end
Given(/^there is a git FETCH_HEAD$/) do
empty_commit
empty_commit
in_current_dir do
File.open(".git/FETCH_HEAD", "w") do |fetch_head|
fetch_head.puts "%s\t\t'refs/heads/made-up' of git://github.com/made/up.git" % `git rev-parse HEAD`.chomp
end
end
run_silent %(git reset --quiet --hard HEAD^)
end
When(/^I make (a|\d+) commits?(?: with message "([^"]+)")?$/) do |num, msg|
num = num == 'a' ? 1 : num.to_i
num.times { empty_commit(msg) }