Як отримати лише один файл з іншої гілки


1261

Я використовую git і працюю над головним відділенням. Ця гілка має файл, який називається app.js.

У мене є experimentвідділення, в якому я зробив купу змін і тонни комісій. Тепер я хочу , щоб об'єднати всі зміни , зроблені тільки app.jsз experimentв masterгалузі.

Як це зробити?

Ще раз я не хочу злиття. Я просто хочу перенести всі зміни app.jsвід experimentгалузі до masterгалузі.



1
На сьогоднішній день виняткова відповідь та інші відповіді, як скопіювати вміст файлу, саме цього я хотів, коли знайшов його. Однак, якщо читати точно, Нік хотів внести зміни, а не повний текст, а файл у файлі masterможе розходитися experiment, наприклад, може містити зміни, об'єднані з інших гілок, які були б втрачені у файл, просто копіюються. PS з іншого боку, він не хоче зливатися, але, наскільки я знаю, git mergeтермін призначений лише для відділення, а не для конкретного файлу, тому тут немає ніяких протиріч.
Олексій Мартьянов

Відповіді:


1599
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

Дивіться також git, як скасувати зміни одного файлу?


Оновлення серпня 2019 року, Git 2.23

З новими git switchта git restoreкомандами, це було б:

git switch master
git restore -s experiment -- app.js

За замовчуванням відновлюється лише робоче дерево.
Якщо ви також хочете оновити індекс (тобто відновити вміст файлу та додати його до індексу однією командою):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

Як згадує Якуб Нарбський у коментарях:

git show experiment:path/to/app.js > path/to/app.js

працює також, за винятком того, що детально описано у питанні SO " Як отримати один файл із конкретної редакції в Git? ", Ви повинні використовувати повний шлях з кореневого каталогу репо.
Звідси шлях / до / app.js, використаний Якубом у своєму прикладі.

Як згадує Мороз у коментарі:

ви отримаєте лише останній стан app.js

Але, для git checkoutабо git show, ви можете насправді посилатися на будь-яку потрібну вам редакцію, як це проілюстровано у питанні ТА " ревізія git checkout файлу в git gui ":

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

було б те саме, що $ FILENAME - це повний шлях до версії файлу.

$REVISIONможе бути як показано на git rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

і так далі.

schmijos додає в коментарях :

Ви також можете це зробити із скрині:

git checkout stash -- app.js

Це дуже корисно, якщо ви працюєте в двох відділеннях і не хочете брати на себе зобов'язання.


13
Одне зауваження: ви отримаєте лише останній стан app.js, ви не отримаєте жодної історії, що переноситься з гілки експерименту.
Морозний

2
@ThomasReggi ви повинні мати можливість імпортувати (замовити) файл з будь-якої гілки до будь-якої поточної гілки. Якщо ви не можете, це може бути гарним питанням, щоб задати тут, з конкретними деталями, такими як точне повідомлення про помилку та використана версія Git та ОС.
VonC

2
У підкаталозі ви також можете використовувати experiment:./app.js. (Вам не потрібно вказувати повний шлях.) Я дізнався це завдяки дуже корисному повідомленню про помилку, яке мені дало git: "Ви мали на увазі" mybranch: full / path / to / my / file.xsl 'aka "mybranch: ./file.xsl '? " Так! Я не думаю, що я ніколи не був у захваті від фатального повідомлення про помилку.
Еван Ленц

1
@TomaszGandor Так, я зазначу, що в stackoverflow.com/a/21066489/6309 , де git show не змінює індекс, але git checkout змінює індекс.
VonC

1
@FriedBrice Дивіться мою відповідь: сьогодні б це булоgit restore -s new-feature path/to/app.js
VonC

359

Все набагато простіше, використовуйте для цього git checkout.

Припустимо, you're on masterгілка, щоб отримати app.js from new-featureвідділення:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

Це дозволить отримати вміст потрібного файлу. Ви можете, як завжди, використовувати частину sha1 замість нової функції гілки, щоб отримати файл таким, яким він був у цій конкретній комісії.

Примітка : new-featureмає бути локальним відділенням, а не віддаленим.


76
Мені корисно завжди вказувати походження, git checkout origin/source_branch path/to/fileтому що якщо ви нехтували оновленням вихідної гілки вашого локального репо, ви можете отримати стару версію файлу ... Запитайте мене, як я знаю. ;)
талірик

2
@Mymozaaa питання не згадувало про віддалені, таким чином припущення, що це суто місцеве репо
Дмитро Автономов

1
Чи приведе ця команда історію файлу чи лише останню версію файлу?
користувач1366265

1
@ user1366265 ця команда помістить файл таким, яким він був у конкретному документі, який ви вказали, або голові гілки, яку ви вказали. Немає такого поняття, як "історія файлу", вся інформація історії зберігається лише у гілках.
Дмитро Автономов

3
Здається, це автоматично ставить файл із виїздом. Чи можна зробити те ж саме без постановки?
bluenote10

44
git checkout branch_name file_name

Приклад:

git checkout master App.java

Це не спрацює, якщо в назві вашої філії є період.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.

@PhilipRego Ця відповідь правильна. Я здогадуюсь, що у вашій гілці є велика література чи розділові знаки, або у вас є лише віддалена гілка, а не локальна. Перегляньте документ git checkout doc: git-scm.com/docs/git-checkout#Documentation/…
Bret

@Bret Я виявив, що це не працює, коли назва філії має крапку. Я запропонував редагувати
Філіп Рего

Це найкраща відповідь. Я хочу, щоб ця відповідь була найвищою. Поточний найвищий показник дуже заплутаний і не простий
Рассел Лего

41

Доповнення до відповідей VonC та chhh.

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

або

git checkout experiment -- app.js

2
Класно! Я ненавиджу вказувати довгі шляхи. Чи --необов’язковий подвійний тире ( ) між назвою гілки та шляхами? Хіба тільки для того, щоб запобігти трактуванню шляхів, які починалися з тире, як варіанти / перемикачі?
Томаш Гандор

Чесно кажучи, я не знаю. Я навіть не помітив, що забув подвійний тире, поки ти не вказав на це.
AlexLordThorsen

6
@TomaszGandor Не --є обов'язковим, але корисніше уникати конфлікту з іменами філій. Наприклад, git checkout -- fooозначає "перевірити файл foo з HEAD" (тобто перезаписати локальні зміни в foo , тобто підмножину git reset --hard), але це git checkout fooможе означати це або "переходимо до гілки foo ".
Алоїз Магдал

8

Або якщо ви хочете, щоб усі файли з іншої гілки:

git checkout <branch name> -- .

23
Початковий квест містить "лише один файл".
greatvovan

1
це замінює наявні файли, а не об'єднує
Amare

3
Це .робить величезну різницю: замість того, щоб переходити до іншої гілки, вона копіює звідти всі файли, залишаючи вас на поточному. Ви отримуєте вміст з іншої галузі, не вникаючи в нього.
Xeverous

4

Перегляньте файл на github і витягніть його звідти

Це прагматичний підхід, який безпосередньо не відповідає ОП, але деякі вважають корисним:

Якщо відповідна гілка знаходиться на GitHub, ви можете перейти до потрібної гілки та файлу за допомогою будь-якого з багатьох інструментів, які пропонує GitHub, а потім натиснути «Raw», щоб переглянути звичайний текст, та (необов'язково) скопіювати та вставити текст як бажаний.

Мені подобається такий підхід, оскільки він дозволяє переглядати віддалений файл у повному обсязі, перш ніж перетягнути його на свою локальну машину.


2
Однак копіювання та вставлення необробленого файлу, ймовірно, спричинить небажані зміни символів у вашому git diff. Безпечніше зберегти файл безпосередньо у вашому проекті, щоб не змінитись.
Філіп Рего

0

Якщо ви хочете, щоб файл з певної комісії (будь-якої гілки), скажіть 06f8251f

git checkout 06f8251f path_to_file

Наприклад, у Windows:

git checkout 06f8251f C: \ A \ B \ C \ D \ file.h


1
Дякуємо, що знайшли час для відповіді! Але це не дає відповіді на запитання, і хороша відповідь, яка дуже деталізована, вже була розміщена 9 років тому. Не потрібно наштовхуватися на питання.
Натан

Це дійсний практичний сценарій. Відповідь стосується правильно галузі, але що робити з переглядом конкретної комісії гілки.
arupjbasu

0

Інший спосіб - створити патч з відмінностями та застосувати його у головній гілці, наприклад. Скажімо, остання фіксація перед тим, як ви почали працювати над app.js, - це 00000aaaaa, а комісія, що стосується потрібної версії, - 00000bbbbb

Ви запускаєте це в гілці експерименту:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

Це створить файл із усіма відмінностями між цими двома комітами для app.js, який ви можете застосувати куди завгодно. Ви можете зберігати цей файл у будь-якому місці поза проектом

Тоді в master ви просто запустите:

git apply ~/app_changes.git

тепер ви побачите зміни в проектах так, ніби ви їх зробили вручну.


-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Сподіваюся, що це вам допоможе. Будь ласка, дайте мені знати, якщо у вас є запити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.