গিট প্যারেন্ট পয়েন্টারকে আলাদা পিতামাতায় সেট করা


220

অতীতে যদি আমার কোন প্রতিশ্রুতি থাকে যা একজন পিতামাতার প্রতি নির্দেশ করে তবে আমি যে পিতামাতার প্রতি ইঙ্গিত করে তা পরিবর্তন করতে চাই, আমি কীভাবে তা করব?

উত্তর:


404

ব্যবহার git rebase। গিটে এটি "জেনারেল (কমিট) নিতে এবং এটি আলাদা প্যারেন্ট (বেস)" কমান্ডে এটিকে / তাদেরকে প্লপ করুন।

তবে কিছু বিষয় জানতে হবে:

  1. যেহেতু প্রতিশ্রুতিবদ্ধ SHAগুলি তাদের পিতামাতার সাথে জড়িত, আপনি যখন কোনও প্রদত্ত প্রতিশ্রুতিটির পিতামাতাকে পরিবর্তন করবেন তখন তার এসএইচএ পরিবর্তিত হবে - যেমন তার পরে আসা সমস্ত কমিটের এসএইচএগুলি (এটির চেয়ে সাম্প্রতিক) উন্নয়নের লাইনে আসবে।

  2. আপনি যদি অন্য লোকের সাথে কাজ করছেন, এবং আপনি ইতিমধ্যে প্রশ্নে প্রকাশ্যে প্রতিশ্রুতিবদ্ধ করেছেন যে তারা এটিকে কোথায় টেনে নিয়েছে, প্রতিশ্রুতি সংশোধন করা সম্ভবত একটি খারাপ ধারণা ™ এটি # 1 এর কারণে এবং এর ফলে আপনার এসএইচএগুলির কারণে "একই" কমিটের সাথে আর মেলে না বলে কী ঘটেছিল তা নির্ধারণের চেষ্টা করার সময় অন্য ব্যবহারকারীদের ভান্ডারগুলির মুখোমুখি হবে। (বিশদগুলির জন্য লিঙ্কযুক্ত ম্যান পেজের "পুনরায় পুনরুদ্ধার" বিভাগটি দেখুন))

এটি বলেছে, আপনি যদি বর্তমানে কোনও শাখায় কিছু কমিট করে যে আপনি নতুন পিতামাতার কাছে যেতে চান তবে এটি দেখতে এরকম কিছু দেখতে চাইবে:

git rebase --onto <new-parent> <old-parent>

এটি বর্তমান শাখার পরে সমস্ত কিছুকে তার পরিবর্তে <old-parent>উপরে বসতে সরিয়ে দেবে <new-parent>


আমি পিতামাতার পরিবর্তন করতে গিট রিবেস --অন্টো ব্যবহার করছি তবে মনে হচ্ছে আমি কেবল একক প্রতিশ্রুতি দিয়ে শেষ করেছি। আমি এটিতে একটি প্রশ্ন রেখেছি: স্ট্যাকওভারফ্লো.com
এডুয়ার্ডো মেলো

7
আহা, তাই এটি কি --ontoজন্য ব্যবহৃত হয়! ডকুমেন্টেশন সবসময় সম্পূর্ণরূপে আমাকে অস্পষ্ট হয়েছে, এমনকি এই উত্তরটি পড়ার পর!
ড্যানিয়েল সি সোব্রাল

6
এই লাইন: আমি এখন পর্যন্ত যে অন্যান্য প্রশ্ন এবং নথিটি পড়েছি তা git rebase --onto <new-parent> <old-parent>কীভাবে ব্যবহার করতে হবে rebase --ontoসে সম্পর্কে আমাকে সবকিছু বলুন ।
jpmc26

3
আমার জন্য এই আদেশটি পড়া উচিত: rebase this commit on that oneবা git rebase --on <new-parent> <commit>। এখানে পুরানো পিতামাতাকে ব্যবহার করা আমার কাছে বোধগম্য নয়।
সমীর আগুইয়ার

1
@ কোপরাব আপনি যখন আপনার মাথা থেকে দূরবর্তী মাথার কিছু পথ ফেলে দিতে চান তখন পুরানো পিতা বা মাতা গুরুত্বপূর্ণ। কেস আপনি বর্ণনা দ্বারা পরিচালিত হয় git rebase <new-parent>
ক্লেক

35

যদি এটির সক্রিয় হয়ে যায় যে আপনাকে পরবর্তী কমিটিগুলি ছাঁটাই করা এড়াতে হবে (উদাহরণস্বরূপ, কারণ ইতিহাস পুনর্লিখনটি অক্ষম হবে) তবে আপনি গিট প্রতিস্থাপন (গিট ১.6.৫ এবং তার পরে পাওয়া যাবে) ব্যবহার করতে পারেন ।

# …---o---A---o---o---…
#
# …---o---B---b---b---…
#
# We want to transplant B to be "on top of" A.
# The tree of descendants from B (and A) can be arbitrarily complex.

replace_first_parent() {
    old_parent=$(git rev-parse --verify "${1}^1") || return 1
    new_parent=$(git rev-parse --verify "${2}^0") || return 2
    new_commit=$(
      git cat-file commit "$1" |
      sed -e '1,/^$/s/^parent '"$old_parent"'$/parent '"$new_parent"'/' |
      git hash-object -t commit -w --stdin
    ) || return 3
    git replace "$1" "$new_commit"
}
replace_first_parent B A

# …---o---A---o---o---…
#          \
#           C---b---b---…
#
# C is the replacement for B.

উপরোক্ত প্রতিস্থাপনটি প্রতিষ্ঠিত হওয়ার সাথে, বস্তু বি এর জন্য যে কোনও অনুরোধগুলি আসলে বস্তু সিটি ফিরিয়ে দেবে সি এর বিষয়বস্তু হ'ল প্রথম পিতা বা মাতা (একই পিতা-মাতা (প্রথম ব্যতীত), একই গাছ ব্যতীত বি এর সামগ্রীর মতো, একই প্রতিশ্রুতি বার্তা)।

প্রতিস্থাপনগুলি ডিফল্টরূপে সক্রিয় থাকে তবে গিট করার --no-replace-objectsবিকল্পটি (কমান্ডের নামের আগে) ব্যবহার করে বা পরিবেশের ভেরিয়েবল সেট করেই পরিবর্তন করা যায়। প্রতিস্থাপনগুলি ধাক্কা দিয়ে ভাগ করা যায় (স্বাভাবিক ছাড়াও )।GIT_NO_REPLACE_OBJECTSrefs/replace/*refs/heads/*

আপনি পছন্দ করেন না এমন কমিট-munging (সঙ্গে সম্পন্ন sed উপরে), তাহলে আপনি উচ্চ স্তরের কমান্ড ব্যবহার কমিট আপনার প্রতিস্থাপন তৈরি করা যায়নি:

git checkout B~0
git reset --soft A
git commit -C B
git replace B HEAD
git checkout -

বড় পার্থক্যটি হ'ল এই ক্রমটি অতিরিক্ত অভিভাবকদের প্রচার করে না যদি বি একটি মার্জ কমিট হয়।


এবং তারপরে, আপনি কীভাবে বিদ্যমান সংগ্রহস্থলগুলিতে পরিবর্তনগুলি ঠেলাবেন? এটি স্থানীয়ভাবে কাজ করছে বলে মনে হচ্ছে, তবে গিট পুশ এর পরে কিছুই
চাপায় না

2
@ ব্যাপটিস্টউইচট: প্রতিস্থাপনগুলি আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা সেট (সেট) এ সংরক্ষণ করা হবে। আপনাকে refs/replace/রেফার হায়ারার্কি ধাক্কা দেওয়ার (এবং আনতে) ব্যবস্থা করতে হবে । আপনার যদি একবার এটি করার দরকার হয় তবে আপনি git push yourremote 'refs/replace/*'উত্স সংগ্রহস্থল এবং git fetch yourremote 'refs/replace/*:refs/replace/*'গন্তব্য সংগ্রহস্থলগুলিতে করতে পারেন। যদি আপনার এটি একাধিকবার করার প্রয়োজন হয় তবে তার পরিবর্তে আপনি সেই সংশোধনগুলি একটি remote.yourremote.pushকনফিগার ভেরিয়েবল (উত্স সংগ্রহস্থলীতে) এবং একটি remote.yourremote.fetchকনফিগার ভেরিয়েবল (গন্তব্য সংগ্রহস্থলগুলিতে) যুক্ত করতে পারেন।
ক্রিস জনসেন

3
এটি করার একটি সহজ উপায় হ'ল ব্যবহার করা git replace --grafts। কখন এটি যুক্ত করা হয়েছিল তা নিশ্চিত নয়, তবে এর পুরো উদ্দেশ্যটি প্রতিস্থাপন তৈরি করা যা প্রতিশ্রুতি বি হিসাবে সমান তবে নির্দিষ্ট পিতামাতার সাথে।
পল ওয়াগল্যান্ড

32

দ্রষ্টব্য যে গিটে প্রতিশ্রুতিবদ্ধকরণের পরিবর্তনের জন্য এটির অনুসরণকারী সমস্ত প্রতিশ্রুতি পরিবর্তন করা দরকার। আপনি যদি ইতিহাসের এই অংশটি প্রকাশ করেন তবে নিরুৎসাহিত করা হয় এবং কেউ কেউ ইতিহাস নিয়ে তাদের কাজ তৈরি করতে পারে যা পরিবর্তনের আগে ছিল।

কিছু করতে বিকল্প সমাধান git rebaseউল্লেখ অ্যাম্বার প্রতিক্রিয়া ব্যবহার করা গ্রাফট (দেখুন গীত সংজ্ঞা গ্রাফট প্রক্রিয়া গীত শব্দকোষ এবং ডকুমেন্টেশন .git/info/graftsফাইল গীত সংগ্রহস্থলের প্রয়োগ লেআউট ডকুমেন্টেশন) একটি কমিট পরিবর্তনের পিতা বা মাতা থেকে, চেক এটি কিছু ইতিহাস প্রদর্শকের সঠিক জিনিস করেনি ( gitk, git log --graph, ইত্যাদি) এবং তারপরে git filter-branchএটি স্থায়ী করতে (এবং তারপরে গ্রাফট অপসারণ করুন এবং বিকল্পের সাহায্যে ব্যাকআপ করা মূল git filter-branchরেফগুলি সরিয়ে ফেলুন , অথবা পুনরায় সংগ্রহস্থলটি পুনরুদ্ধার করুন) ব্যবহার করুন (তার মানচিত্রের "উদাহরণ" বিভাগে বর্ণিত হিসাবে )

প্রতিধ্বনি "$ কমিট-আইডি $ গ্রাফ্ট আইডি" >> গিট / তথ্য / গ্রাফ্ট
গিট ফিল্টার-শাখা $ গ্রাফ্ট-আইডি..ইইএইড

বিঃদ্রঃ !!! এই সমাধান রি-বেসের ফলে সমাধান থেকে বিভিন্ন যে git rebaseরি-বেসের ফলে যাবে / ট্রান্সপ্লান্ট পরিবর্তন , গ্রাফট ভিত্তিক সমাধান কেবল reparent করে হতে পার, অথচ হিসাবে , পুরাতন পিতা বা মাতা এবং নতুন পিতা বা মাতা মধ্যে অ্যাকাউন্ট পার্থক্য গ্রহণ না!


3
আমি যা বুঝতে পারি তা থেকে ( git.wiki.kernel.org/index.php/GraftPoint ) থেকে git replaceগিট গ্রাফসকে ছাড়িয়ে গেছে (ধরে নিলে আপনার গিট 1.6.5 বা তার পরে আছে)।
আলেকজান্ডার বার্ড

4
@ থ্র 4 ওএন: বেশিরভাগ ক্ষেত্রে সত্য, তবে আপনি যদি ইতিহাস পুনরায় লিখতে চান তবে গ্রাফ্টস + গিট-ফিল্টার-শাখা (বা ইন্টারেক্টিভ রিবেস, বা দ্রুত এক্সপোর্ট + যেমন রেপোসার্জন) এটি করার উপায়। আপনি যদি ইতিহাস সংরক্ষণের প্রয়োজন / চান তবে গ্রাট-রিপ্লেস গ্রাফ্টের চেয়ে অনেক বেশি উন্নত।
জাকুব নরবস্কি

@ জাকুবনারাইবস্কি, ইতিহাস সংরক্ষণ করুন বনাম পুনর্লিখন দ্বারা আপনি কী বোঝাতে চেয়েছিলেন ? আমি কেন + ব্যবহার করতে পারি না ? আমার পরীক্ষায়, পুরো গাছটি রিবায়েস করে প্রতিস্থাপনের প্রতি শ্রদ্ধা জানিয়েছিল। git-replacegit-filter-branchfilter-branch
cdunn2001

1
@ সিডুন ২০০২: git filter-branchইতিহাস পুনর্লিখন, গ্রাফ্ট এবং প্রতিস্থাপনের প্রতি শ্রদ্ধা (তবে পুনর্লিখিত ইতিহাসে প্রতিস্থাপনগুলি মোটা হবে); ঠেলাঠেলি ফলস-ফরোয়ার্ড পরিবর্তন না করে। git replaceস্থানান্তর স্থানান্তরযোগ্য প্রতিস্থাপন তৈরি করে; পুশ দ্রুত-অগ্রসর হবে, তবে refs/replaceইতিহাস সংশোধন করতে আপনাকে প্রতিস্থাপন স্থানান্তর করার জন্য ধাক্কা দিতে হবে। এইচটিএইচ
জাকুব নারেবস্কি

23

উপরের উত্তরগুলি স্পষ্ট করতে এবং নির্লজ্জভাবে আমার নিজের স্ক্রিপ্টটি প্লাগ করতে:

এটি "রিবেস" করতে চান বা "পিতামাতা" করতে চান তার উপর নির্ভর করে। অ্যাম্বারের পরামর্শ অনুসারে একটি রিবেস ডিফএসের কাছাকাছি চলে । জাকুব এবং ক্রিসের পরামর্শ অনুসারে একজন পিতা-মাতা পুরো গাছের স্ন্যাপশট ঘুরে বেড়ান । আপনি যদি পিতামাতা করতে চান তবে আমি কাজটি নিজে হাতে না করে ব্যবহার করার পরামর্শ দিচ্ছি ।git reparent

তুলনা

ধরুন আপনার বাম দিকে ছবিটি রয়েছে এবং আপনি এটি ডানদিকের ছবির মতো দেখতে চান:

                   C'
                  /
A---B---C        A---B---C

রিবাজিং এবং রিপ্রেটিং উভয়ই একই চিত্র তৈরি করবে তবে এর সংজ্ঞা C'আলাদা fers সহ git rebase --onto A B, C'দ্বারা প্রবর্তিত কোনও পরিবর্তন থাকবে না B। সহ git reparent -p A, C'অভিন্ন হবে C(বাদে Bএটি ইতিহাসে হবে না)।


1
+1 আমি reparentস্ক্রিপ্টটি নিয়ে পরীক্ষা-নিরীক্ষা করেছি ; এটি সুন্দরভাবে কাজ করে; অত্যন্ত প্রস্তাবিত । আমি কল করার আগে একটি নতুন branchলেবেল তৈরি করার এবং checkoutসেই শাখায় সুপারিশ করব (যেমন শাখা লেবেলটি সরবে)।
রোববার্ব

এটিও লক্ষণীয় যে: (1) মূল নোড অক্ষত রয়েছে এবং (2) নতুন নোডটি মূল নোডের সন্তানদের উত্তরাধিকার সূত্রে পায় না।
রোববার্ব

0

আমি যখন ওপি হিসাবে ঠিক একই জিনিসটি চেষ্টা করছিলাম তখন অবশ্যই @ জাকুবের উত্তর আমাকে বেশ কয়েক ঘন্টা আগে সহায়তা করেছিল।
যাইহোক, git replace --graftএখন গ্রাফ্ট সংক্রান্ত সহজ সমাধান। এছাড়াও, সমাধানটি নিয়ে একটি বড় সমস্যা হ'ল ফিল্টার-শাখা আমাকে প্রতিটি শাখা HEিলে করে। তারপরে, git filter-repoনিখুঁতভাবে এবং নির্দোষভাবে কাজটি করেছেন।

$ git replace --graft <commit> <new parent commit>
$ git filter-repo --force

আরও তথ্যের জন্য: দস্তাবেজগুলিতে "পুনরায় গ্রাফটিংয়ের ইতিহাস" বিভাগটি দেখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.